Post on 06-Apr-2015
Learning By Doing
Klassenhierarchien, Vererbung• Objekte werden in der Regel in Klassenhierarchien klassifiziert
Beispiel: Europäische SäugetiereSäugetier
Insektenfresser Nagetier Huftier
Igel Spitzmaus Maulwurf Marder Pferd Rind
Raubtier
Hörnchen Biber Bär Katze Schwein
• Einfachvererbung: nur eine Superklasse
• is-a-Relation: Ein Objekt der Unterklasse ist auch ein Objekt der Superklasse
• Grundidee: Erweiterung der Eigenschaften und des Verhaltens durch Vererbung
• Manchmal auch: Veränderung des Verhaltens in der abgeleiteten Klasse (Überschreiben)
• Aber nie: Entfernen von Eigenschaften und Verhalten in der abgeleiteten Klasse
Oberklasse, Superklasse, Basisklasse Unterklasse,
abgeleitete Klasse
"Alle guten und schlechten Eigenschaften werden vererbt"
s. Buch S. 153ff
// MoireIs.java
import ch.aplu.util.*;
class MoireIs extends GPanel{ MoireIs() { 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); }
public static void main(String[] args) { new MoireIs(); }}
Learning By Doing
Vererbung durch extendsWir vererben alle Eigenschaften des GPanels einer Klasse MoireIs
s. Buch S. 157
MoireIs ist-ein GPanel
Konstruktor Superklasse
line() ist Methode von MoireIs
// MoireHas.java
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); }
public static void main(String[] args) { new MoireHas(); }}
Learning By Doing
Komposition statt VererbungWir konstruieren die Klasse MoireHas unter Verwendung eines GPanels
s. Buch S. 156
MoireHas hat-ein GPanel
MoireHas verwendet das GPanel
Learning By Doing
Klassendiagramme (UML, unified modeling language)• zur Dokumentation• zur besseren Übersicht und zum besseren Verständnis• zur automatischen Codegeneration (Wunsch)
Tasten-instrument
Klavier
is-a
Vererbung(is-a)
Klavier
Tasten
spielen()
Tastehas-a
Komposition(has-a)
Polygon
Parallelo-gramm
show()
Point2D.Double[] corners
Rechteck
Quadrat
Dreieck
GleichseitigesDreieck
Point2D.Doubledouble xdouble y
has-aPolyEx2
main()
int sizeGPanel panelGPanel
uses
has-a
is-a
is-a
is-a
is-a
uses
• Typischer Klassenentwurf (Polygone)
s. Buch S. 160ff
Pfeilzur Superklasse
Raute zurumgebenden Klasse
Learning By Doing
Zugriffsbezeichner (Package-Konzept)Semantische Fehler (Fehler zur Laufzeit des Programms) sind oft auf die fehlerhafte Veränderung von Daten zurück-zuführen. Man muss die Daten vor dem unerlaubten Zugriff schützen (Datenkapselung).
s. Buch S. 172ff
• 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)
Schutzmechanismen:
Learning By Doing
Zugriffsbezeichner für Klassen, Instanzvariablen und Methoden
s. Buch S. 172
Zugriffs-bezeichner
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
Turtle
is-a
TurtleKid
setHomeland()
Turtle()Turtle(Turtle t)forward()...
getHomeland()shape()
is-a
TurtleBoy
shape()
TurtleGirl
shape()
package homeland
Learning By Doing
Musterbeispiel: package homeland
s. Buch S. 173
shape() überschrieben shape() überschrieben
Neue Methode shape()
Learning By Doing// TurtleBoy.java
package homeland;
public class TurtleBoy extends TurtleKid{ public void shape() { label(getHomeland()); for (int i = 0; i < 3; i++) { forward(50); left(120); } }}
// TurtleGirl.java
package homeland;
public class TurtleGirl extends TurtleKid{ public void shape() { label(getHomeland()); for (int i = 0; i < 18; i++) { forward(10); left(20); } }}
// TurtleKid.java
package homeland;
import ch.aplu.turtle.*;
public class TurtleKid extends Turtle{ 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); } }}
extends Turtle
extends TurtleKid
extends TurtleKid
Programme
Learning By Doing
// WbzEx7.java
import homeland.*;
public class WbzEx7{ public WbzEx7() { TurtleKid alois = new TurtleKid(); alois.setHomeland("Emmenthal"); alois.back(50); alois.shape();
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(); }}
Alois, das TurtleKid
Petra, das TurtleGirl
Marcel, der TurtleBoy
WbzEx7
Learning By Doing
Objektorientierte Programmiersprache
s. Buch S. 181ff
• 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();
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
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(); }}
So ...
oder so ...
WbzEx8
Learning By Doing
Musterbeispiel zur Polymorphie
s. Buch S. 192
Bird
whistle()
is-a
Drossel
whistle()
Fink
whistle()
Star
whistle()
Amsel
whistle()
Voliere
whistleAll()
Vector cage
create()creates
class Voliere{ Vector<Bird> cage = new Vector<Bird>(); public void create() {...}
void whistleAll() { for (int i = 0; i < cage.size(); i++) cage.elementAt(i).whistle(); }}
Generischer DatentypTypvariable <Bird>
Es pfeift der richtige Vogel
J2SE V1.4: keine Typvariablen
((Bird)cage.elementAt()).whistle() dafür (unschöner) Cast
Vector cage = new Vector();
Learning By Doing
// Bird.java
public class Bird{ public void whistle() { System.out.println( "Fehler: Vogelvorlage"); }}
// Amsel.java
public class Amsel extends Bird{ public void whistle() { System.out.println( "Amsel pfeift: uiuiii..."); }}
// Fink.java
public class Fink extends Bird{ public void whistle() { System.out.println( "Fink pfeift: zrzrrr..."); }}
// Drossel.java
public class Drossel extends Bird{ public void whistle() { System.out.println( "Drossel pfeift: zwawaaa..."); }}
// Star.java
public class Star extends Bird{ public void whistle() { System.out.println( "Star pfeift: kiukuu..."); }}
Abstrakte Klasse
abstract public class Bird{ abstract public void whistle();}
• Keine Instanzen erlaubt
• Garantieerklärung (Contract) für Unterklassen
Abstrakte Klasse
Learning By Doing
// AmselImp.java
public class AmselImp implements BirdIf{ public void whistle() { System.out.println( "Amsel pfeift: uiuiii..."); }}
// FinkImp.java
public class FinkImp implements BirdIf{ public void whistle() { System.out.println( "Fink pfeift: zrzrrr..."); }}
// DrosselImp.java
public class DrosselImp implements BirdIf{ public void whistle() { System.out.println( "Drossel pfeift: zwawaaa..."); }}
// StarImp.java
public class StarImp implements BirdIf{ public void whistle() { System.out.println( "Star pfeift: kiukuu..."); }}
// BirdIf.java
public interface BirdIf{ public void whistle();}
Interfaces
• Garantieerklärung (Contract) für implementierende Klassen
• Ersatz für Mehrfachvererbung
• Klassengerüste (kein Code)
Interfaces