vererbung

Werbung
Learning By Doing
Klassenhierarchien, Vererbung
• Objekte werden in der Regel in Klassenhierarchien klassifiziert
Beispiel: Europäische Säugetiere
Säugetier
Insektenfresser
Nagetier
Oberklasse, Superklasse,
Basisklasse
Raubtier
Igel Spitzmaus Maulwurf Hörnchen Biber Marder Bär Katze
Unterklasse,
abgeleitete Klasse
Huftier
Pferd Rind Schwein
• Einfachvererbung: nur eine Superklasse
s. Buch
S. 153ff
• is-a-Relation:
Ein Objekt der Unterklasse ist auch ein Objekt der Superklasse
• Grundidee:
Erweiterung der Eigenschaften und des Verhaltens durch Vererbung
"Alle guten und schlechten Eigenschaften werden vererbt"
• Manchmal auch:
Veränderung des Verhaltens in der abgeleiteten Klasse (Überschreiben)
• Aber nie:
Entfernen von Eigenschaften und Verhalten in der abgeleiteten Klasse
Learning By Doing
Vererbung durch extends
Wir vererben alle Eigenschaften des GPanels einer Klasse MoireIs
// MoireIs.java
MoireIs ist-ein GPanel
import ch.aplu.util.*;
class MoireIs extends GPanel
{
MoireIs()
Konstruktor Superklasse
{
super(0, 10, 0, 10);
int i, k;
for (i = 0; i <= 10; i++)
for (k = 0; k <= 10; k++)
line(i, 0, k, 10);
for (i = 0; i <= 10; i++)
for (k = 0; k <= 10; k++)
line(0, i, 10, k);
}
line() ist Methode von MoireIs
public static void main(String[] args)
{
new MoireIs();
}
}
s. Buch S. 157
Learning By Doing
Komposition statt Vererbung
Wir konstruieren die Klasse MoireHas unter Verwendung eines GPanels
// MoireHas.java
MoireHas hat-ein GPanel
import ch.aplu.util.*;
class MoireHas
{
GPanel panel = new GPanel(0, 10, 0, 10);
MoireHas()
{
int i, k;
for (i = 0; i <= 10; i++)
for (k = 0; k <= 10; k++)
panel.line(i, 0, k, 10);
for (i = 0; i <= 10; i++)
for (k = 0; k <= 10; k++)
panel.line(0, i, 10, k);
}
MoireHas verwendet das GPanel
public static void main(String[] args)
{
new MoireHas();
}
}
s. Buch S. 156
Learning By Doing
Klassendiagramme (UML, unified modeling language)
• zur Dokumentation
• zur besseren Übersicht und zum besseren Verständnis
• zur automatischen Codegeneration (Wunsch)
Vererbung
(is-a)
Pfeil
zur Superklasse
Komposition
(has-a)
Tasteninstrum ent
K
l
a
v
i
e
r
h
a
s
a
T
a
s
t
e
n
T
a
s
t
e
s
p
i
e
l
e
n
(
)
is-a
Raute zur
umgebenden Klasse
K lavier
• Typischer Klassenentwurf (Polygone)
Polygon
Point2D.Double[]
corners
show()
uses
has-a
is-a
Parallelogramm
is-a
Rechteck
is-a
GPanel
s. Buch S. 160ff
has-a
PolyEx2
GPanel panel
int size
main()
uses
Quadrat
Point2D.Double
double x
double y
Dreieck
is-a
Gleichseitiges
Dreieck
Learning By Doing
Zugriffsbezeichner (Package-Konzept)
Semantische Fehler (Fehler zur Laufzeit des Programms)
sind oft auf die fehlerhafte Veränderung von Daten zurückzuführen. Man muss die Daten vor dem unerlaubten Zugriff
schützen (Datenkapselung).
Schutzmechanismen:
• Verwendung von Konstanten (Schlüsselwort final)
• Verzicht auf globale Variablen (gibt es in Java nicht)
• Verwendung von lokalen Variablen statt Instanzvariablen
• Zugriffseinschränkungen von Instanzvariablen und Methoden durch
Verwendung von Zugriffsbezeichner (access-specifiers) und durch
einen Programmierstil "so privat wie möglich"
• Zusammenfassung in Klassenbibliotheken (packages)
s. Buch S. 172ff
Learning By Doing
Zugriffsbezeichner für Klassen, Instanzvariablen und Methoden
s. Buch S. 172
Zugriffsbezeichner
Zugriff von
Klassen im
gleichen
Package
Zugriff von
Klassen in
anderen
Packages
Zugriff von
Subklassen
im gleichen
Package
Zugriff von
Subklassen
in anderen
Packages
public
ja
ja
ja
ja
protected
ja
nein
ja
ja
default
ja
nein
ja
nein
private
nein
nein
nein
nein
Learning By Doing
Musterbeispiel: package homeland
Turtle
Turtle()
Turtle(Turtle t)
forward()
...
is-a
package homeland
TurtleKid
setHomeland()
getHomeland()
shape()
Neue Methode shape()
is-a
TurtleBoy
shape()
shape() überschrieben
s. Buch S. 173
TurtleGirl
shape()
shape() überschrieben
Learning By Doing
// TurtleKid.java
// TurtleBoy.java
package homeland;
package homeland;
import ch.aplu.turtle.*;
public class TurtleBoy extends
extends TurtleKid
TurtleKid
{
public void shape()
{
label(getHomeland());
for (int i = 0; i < 3; i++)
{
forward(50);
left(120);
}
}
}
extends Turtle
Turtle
public class TurtleKid extends
{
private String homeland = "";
// Mutator
public void setHomeland(String h)
{
homeland = h;
}
// Accessor
public String getHomeland()
{
return homeland;
}
public void shape()
{
label(homeland);
for (int i = 0; i < 4; i++)
{
forward(50);
left(90);
}
}
}
// TurtleGirl.java
package homeland;
public class TurtleGirl extends
extends TurtleKid
TurtleKid
{
public void shape()
{
label(getHomeland());
for (int i = 0; i < 18; i++)
{
forward(10);
left(20);
}
}
}
Learning By Doing
// WbzEx7.java
import homeland.*;
public class WbzEx7
{
public WbzEx7()
{
TurtleKid alois = new TurtleKid();
alois.setHomeland("Emmenthal");
alois.back(50);
alois.shape();
Alois, das TurtleKid
Petra, das TurtleGirl
TurtleGirl petra = new TurtleGirl();
petra.setHomeland("Zürich");
petra.forward(100);
petra.shape();
TurtleBoy marcel = new TurtleBoy();
marcel.setHomeland("Basel");
marcel.left(90).forward(100);
marcel.shape();
}
public static void main(String[] args)
{
new WbzEx7();
}
}
Marcel, der TurtleBoy
Learning By Doing
Objektorientierte Programmiersprache
• Kapselung
(Klassenbildung)
• Vererbung
(is-a-Hierarchie)
• Polymorphie (Laufzeitbindung)
Polymorphie (Vielgestaltigkeit)
• Klassisch (statische Bindung): bereits zur Compilationszeit ist eindeutig,
welche Methode (Prozedur, Funktion, Subroutine) aufgerufen wird
• OOP (dynamische Bindung, virtuelle Methoden): bei überschriebenen
Methoden wird erst zur Laufzeit ermittelt, welche der Methoden
aufgerufen wird (in Java immer, d.h. alle Methoden sind virtuell)
TurtleKid kid;
...
kid.shape();
s. Buch S. 181ff
Je nachdem, was in diesem Teil des Programms abläuft,
kann hier shape() von TurtleKid, TurtleBoy oder TurtleGirl
aufgerufen werden.
Learning By Doing
// WbzEx8.java
So ...
import homeland.*;
public class WbzEx8
{
public WbzEx8()
{
TurtleKid kid;
if (Math.random() < 0.45)
{
kid = new TurtleGirl();
kid.setHomeland("Zürcher girl");
}
else
{
kid = new TurtleBoy();
kid.setHomeland("Basler boy");
}
kid.shape();
}
public static void main(String[] args)
{
new WbzEx8();
}
}
oder so ...
Learning By Doing
Musterbeispiel zur Polymorphie
Bird
whistle()
is-a
Amsel
whistle()
Drossel
whistle()
Fink
whistle()
Star
whistle()
Voliere
Vector cage
creates
create()
whistleAll()
class Voliere
{
Vector cage =cage
new =Vector();
Vector<Bird>
new Vector<Bird>();
public void create()
{...}
void whistleAll()
{
for (int i = 0; i < cage.size(); i++)
cage.elementAt(i).whistle();
((Bird)cage.elementAt()).whistle()
}
}
s. Buch S. 192
Generischer Datentyp
Typvariable <Bird>
J2SE V1.4:
keine Typvariablen
Es pfeift der richtige Vogel
dafür (unschöner) Cast
Learning By Doing
// Bird.java
Abstrakte Klasse
• Keine Instanzen erlaubt
• Garantieerklärung (Contract)
für Unterklassen
public class Bird
{
public void whistle()
abstract
public class Bird
{
{
System.out.println(
abstract
public
void whistle();
"Fehler:
Vogelvorlage");
} }
}
// Amsel.java
// Drossel.java
public class Amsel extends Bird
{
public void whistle()
{
System.out.println(
"Amsel pfeift: uiuiii...");
}
}
public class Drossel extends Bird
{
public void whistle()
{
System.out.println(
"Drossel pfeift: zwawaaa...");
}
}
// Fink.java
// Star.java
public class Fink extends Bird
{
public void whistle()
{
System.out.println(
"Fink pfeift: zrzrrr...");
}
}
public class Star extends Bird
{
public void whistle()
{
System.out.println(
"Star pfeift: kiukuu...");
}
}
Learning By Doing
Interfaces
• Klassengerüste (kein Code)
// BirdIf.java
• Garantieerklärung (Contract)
für implementierende Klassen
public interface BirdIf
{
public void whistle();
}
• Ersatz für Mehrfachvererbung
// AmselImp.java
// DrosselImp.java
public class AmselImp implements BirdIf
{
public void whistle()
{
System.out.println(
"Amsel pfeift: uiuiii...");
}
}
public class DrosselImp implements BirdIf
{
public void whistle()
{
System.out.println(
"Drossel pfeift: zwawaaa...");
}
}
// FinkImp.java
// StarImp.java
public class FinkImp implements BirdIf
{
public void whistle()
{
System.out.println(
"Fink pfeift: zrzrrr...");
}
}
public class StarImp implements BirdIf
{
public void whistle()
{
System.out.println(
"Star pfeift: kiukuu...");
}
}
Herunterladen