150 likes | 322 Views
Klassenhierarchien, Vererbung. Learning By Doing. Beispiel: Europäische Säugetiere. Oberklasse, Superklasse, Basisklasse. Unterklasse, abgeleitete Klasse. Objekte werden in der Regel in Klassenhierarchien klassifiziert. Einfachvererbung : nur eine Superklasse.
E N D
Klassenhierarchien, Vererbung Learning By Doing Beispiel: Europäische Säugetiere Oberklasse, Superklasse, Basisklasse Unterklasse, abgeleitete Klasse • Objekte werden in der Regel in Klassenhierarchien klassifiziert • 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 "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 s. Buch S. 153ff
Vererbung durch extends Learning By Doing MoireIs ist-ein GPanel // 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(); } } Konstruktor Superklasse line() ist Methode von MoireIs Wir vererben alle Eigenschaften des GPanels einer Klasse MoireIs s. Buch S. 157
Komposition statt Vererbung Learning By Doing MoireHas hat-ein GPanel // 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(); } } MoireHas verwendet das GPanel Wir konstruieren die Klasse MoireHas unter Verwendung eines GPanels s. Buch S. 156
Klassendiagramme (UML, unified modeling language) Learning By Doing Vererbung(is-a) Komposition(has-a) Pfeilzur Superklasse Raute zurumgebenden Klasse • zur Dokumentation • zur besseren Übersicht und zum besseren Verständnis • zur automatischen Codegeneration (Wunsch) • Typischer Klassenentwurf (Polygone) s. Buch S. 160ff
Zugriffsbezeichner (Package-Konzept) Learning By Doing 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 Zugriffschü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
Zugriffsbezeichner für Klassen, Instanzvariablen und Methoden 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 Learning By Doing public ja ja ja ja protected ja nein ja ja default ja nein ja nein private nein nein nein nein s. Buch S. 172
Musterbeispiel: package homeland Learning By Doing Neue Methode shape() shape() überschrieben shape() überschrieben s. Buch S. 173
Programme 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); } } } // 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); } } } // 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); } } } extends TurtleKid extends Turtle extends TurtleKid
WbzEx7 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
Objektorientierte Programmiersprache Learning By Doing Je nachdem, was in diesem Teil des Programms abläuft, kann hier shape() von TurtleKid, TurtleBoy oder TurtleGirl aufgerufen werden. • 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
WbzEx8 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 ...
Musterbeispiel zur Polymorphie Learning By Doing 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(); } } ((Bird)cage.elementAt()).whistle() Vector cage = new Vector(); Generischer DatentypTypvariable <Bird> Es pfeift der richtige Vogel J2SE V1.4: keine Typvariablen dafür (unschöner) Cast s. Buch S. 192
Abstrakte Klasse Learning By Doing Abstrakte Klasse // 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..."); } } abstract public class Bird { abstract public void whistle(); } • Keine Instanzen erlaubt • Garantieerklärung (Contract) für Unterklassen
Interfaces 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 • Klassengerüste (kein Code) • Garantieerklärung (Contract) für implementierende Klassen • Ersatz für Mehrfachvererbung