Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

Vererbung.

Ähnliche Präsentationen


Präsentation zum Thema: "Vererbung."—  Präsentation transkript:

1 Vererbung

2 Das Prinzip der Vererbung im täglichen Leben:

3 Walter besitzt ein Haus.

4 Walter erbt nun 10000Euro. Also besitzt er insgesamt:
+ 10000

5 Erben (abgeleitete Klasse) selbst basteln
In Java: Erblasser ---> Erbe In Java darf man einen Erben (abgeleitete Klasse) selbst basteln abgeleitete Klasse Basisklasse --->

6 Statt Basisklasse sagt man auch: Oberklasse, Vaterklasse

7 Statt abgeleiteter Klasse sagt man auch: Unterklasse, Sohnklasse, Subklasse

8 Eine abgeleitete Klasse wird in Java wie folgt angegeben:
class Ei extends Huhn{ ... } Bezeichner Basisklasse abgeleitete Klasse

9 Die abgeleitete Klasse (kurz: Ableitung) besitzt automatisch alle Member (Ausnahme: Konstruktor) der Basisklasse.

10 Beispiel:

11 Von einem Flachdachhaus wird ein Modell (Draufsicht) erstellt:

12 Der Einfachheit halber wird nur die Grundfläche (ohne Zimmer, usw
Der Einfachheit halber wird nur die Grundfläche (ohne Zimmer, usw.) des Hauses abgebildet. Aufgabe: Realisieren Sie die Klasse Modell in Java.

13 class Modell{ private double l; private double b; public Modell(double pl, double pb){ l = pl; b = pb; } public void setL(double pl){ } // weiter...

14 public void setB(double pb){
b = pb; } public double getL(){ return(l); public double getB(){ return(b); public double getFlaeche(){ return(l*b); };

15 Jetzt soll ein “genaueres“ Modell des Flachdachhauses erstellt werden: Modell aus Styropor (oder Ton). Aufgabe: Realisieren Sie in Java die Klasse Gmodell.

16 Standardmäßig könnte man das mit den 3 Attributen Länge, Breite, Höhe und den zugehörigen set- und get-Methoden machen. Also wie folgt:

17 class Gmodell{ private double l; private double b; private double h; public Gmodell(double pl, double pb, double ph){ l = pl; b = pb; h = ph; }

18 public void setL(double pl){
l = pl; } public void setB(double pb){ b = pb; public double getL(){ return(l); public double getB(){ return(b);

19 public void setH(double ph){
h = ph; } public double getH(){ return(h); public double getVolumen(){ return(l*b*h); };

20 Gibt es eine andere Lösung, bei der man sich Schreibarbeit sparen kann
Gibt es eine andere Lösung, bei der man sich Schreibarbeit sparen kann? Wie kann man Softwareteile dabei wiederverwenden ? Indem man die Vererbung benutzt.

21 Welche Member der Klasse Modell kann man übernehmen (erben)
Welche Member der Klasse Modell kann man übernehmen (erben) ? Welche Member kommen neu dazu ?

22 Welche Member müssen neu dazu ?
class Modell{ private double l; private double b; public Modell(double pl, double pb){... public void setL(double pl){... public void setB(double pb){... public double getL(){... public double getB(){... public double getFlaeche(){... }; Alle außer dem Konstruktor Welche Member müssen neu dazu ? Welche Member werden vererbt ?

23 public void setL(double pl){... public void setB(double pb){...
extends Modell{ class Gmodell private double l; private double b; public: public void setL(double pl){... public void setB(double pb){... public double getL(){... public double getB(){... public double getFlaeche(){... } Die reliefförmig dargestellten Member werden geerbt. private double h; Wie wird eine Vererbung erreicht ? Die rot dargestellten Member kommen neu dazu. public Gmodell(double pl, double pb,double ph){... public void setH(double ph){... public double getH(){... public double getVolumen(){...

24 Aufgabe: Schreiben Sie das komplette Programm mit den zugehörigen Klassen in Java

25 public class MainVererbung1{
public static void main(String[] args){ // Anweisungen siehe später } class Modell{ private double l; private double b; public Modell(double pl, double pb){ l = pl; b = pb;

26 public void setL(double pl){
l = pl; } public void setB(double pb){ b = pb; public double getL(){ return(l); public double getB(){ return(b); public double getFlaeche(){ return(l*b); };

27 class Gmodell extends Modell{ private double h;
public Gmodell(double pl, double pb, double ph){ super(pl,pb); setH(ph); } public void setH(double ph){ h = ph; public double getH(){ return(h); public double getVolumen(){ return(getFlaeche()*h); Diese Methode gibt es nicht in der Klasse Gmodell. Warum kann sie trotzdem verwendet werden? Weil ... 1) Die Methode von der Klasse Modell vererbt wird und es sie deshalb in Gmodell gibt 2) Weil die Methode public ist, kann auf sie zugegriffen werden. Mit super wird ein Konstruktor der Oberklasse aufgerufen. Näheres dazu später.

28 class Gmodell extends Modell{ private double h;
public Gmodell(double pl, double pb, double ph){ super(pl,pb); setH(ph); } public void setH(double ph){ h = ph; public double getH(){ return(h); public double getVolumen(){ return(getFlaeche()*h); Wie heißt der Konstruktor der Oberklasse und wie viele Parameter hat er? Der Konstruktor heißt Modell und er hat zwei Parameter

29 class Gmodell extends Modell{ private double h;
public Gmodell(double pl, double pb, double ph){ super(pl,pb); setH(ph); } public void setH(double ph){ h = ph; public double getH(){ return(h); public double getVolumen(){ return(getFlaeche()*h); Was könnte man statt dem Aufruf der Methode setH(ph) auch noch machen? h = ph;

30 Warum ist folgende Lösung falsch?

31 class Gmodell extends Modell{ private double h;
public Gmodell(double pl, double pb, double ph){ super(pl,pb); setH(ph); } public void setH(double ph){ h = ph; public double getH(){ return(h); double getVolumen(){ return(b*l*h); Warum ist diese Lösung falsch ? Die Member b und l gibt es zwar in der Klasse GModell (sie wurden vererbt). Allerdings sind sie private. Auf vererbte private-Member kann weder innerhalb noch außerhalb der Klasse zugegriffen werden.

32 class Gmodell extends Modell{ private double h;
public Gmodell(double pl, double pb, double ph){ super(pl,pb); setH(ph); } public void setH(double ph){ h = ph; public double getH(){ return(h); double getVolumen(){ return(b*l*h); Die Methoden getB() und getL() sind public. Deswegen dürfen sie benutzt werden. Welche Lösung wäre auch noch möglich? return(getB()*getL()*h);

33 class Gmodell extends Modell{ private double h;
public Gmodell(double pl, double pb, double ph){ super(pl,pb); setH(ph); } public void setH(double ph){ h = ph; public double getH(){ return(h); double getVolumen(){ return(b*l*h); h wird nicht vererbt und ist ein Attribut von Gmodell. Deshalb kann man innerhalb der Klasse Gmodell auf h zugreifen. Warum muss man getB() und getL() verwenden, aber nicht getH(), sondern h ? return(getB()*getL()*h);

34 class Gmodell extends Modell{ private double h;
public Gmodell(double pl, double pb, double ph){ super(pl,pb); setH(ph); } public void setH(double ph){ h = ph; public double getH(){ return(h); double getVolumen(){ return(pb*pl*h); Warum ist das nicht korrekt? Auf die Variablen pb und pl kann nicht zugegriffen werden, da sie weder ... ein Attribut der Klasse, noch ein Parameter bzw. eine lokale Variable der Methode getVolumen() sind.

35 public Gmodell(double pl, double pb, double ph){ super(pl,pb);
setH(ph); } Da die Klasse Gmodell von der Klasse Modell erbt, muss beim Anlegen eines Objekts der Klasse Gmodell auch der Konstruktor der Klasse Modell aufgerufen werden. Wird dies nicht gemacht, dann wird automatisch (ohne Zutun des Programmierers) der Standardkonstruktor der Klasse Modell aufgerufen. Was passiert, wenn der Standardkonstruktor nicht existiert ? Dann wird dieser automatisch vom Compiler angelegt, außer .... es gibt einen Konstruktor mit (1, 2, 3, ...) Parametern. Dann liefert der Compiler eine Fehlermeldung.

36 Merke Wenn ein Konstruktor der Unterklasse nicht mittels super(
Merke Wenn ein Konstruktor der Unterklasse nicht mittels super(...) einen Konstruktor der Oberklasse aufruft, dann wird automatisch der Standardkonstruktor (=Konstruktor mit 0 Parametern) der Oberklasse aufgerufen. Der Sinn davon ist, dass alle Attribute (auch die der Oberklassen) einen definierten Wert bekommen sollen, auch wenn der Programmierer vergisst, den Konstruktor der Oberklasse aufzurufen.

37 Falls dieser Standardkonstruktor nicht existiert, wird er automatisch vom Compiler erzeugt, außer ein anderer Konstruktor (mit mindestens einem Parameter) existiert schon. In diesem Fall bringt der Compiler dann eine Fehlermeldung. Wenn man super(...) in einem Konstruktor benutzt, muss dies die erste Anweisung in dem Konstruktor sein, d.h. vor super(...) darf keine Anweisung stehen!

38 public Gmodell(double pl, double pb, double ph){ super(pl,pb);
setH(ph); } Was würde also geschehen, wenn man diese Anweisung in unserem Programm weglassen würde? Dann würde automatisch der Standardkonstruktor der Klasse Modell aufgerufen werden. Da dieser nicht existiert und er auch nicht automatisch erzeugt wird (da es ja schon in der Klasse Modell einen Konstruktor mit zwei Parametern gibt) meldet der Kompiler einen Fehler.

39 Beispiel für die Benutzung der o. g. Klassen in einem Hauptprogramm
Beispiel für die Benutzung der o.g. Klassen in einem Hauptprogramm. Welche Werte bekommen die Variablen in den Zuweisungen?

40 public class MainVererbung1{ public static void main(String[] args){
Modell m = new Modell(10,20); Gmodell g = new Gmodell(2,3,4); double a,b,c,f,v; // ... } Bevor wir näher auf die einzelnen Anweisungen eingehen, noch eine Frage: Was ist streng genommen falsch bei dem Aufruf mit den obigen Parametern Die Parameter müssen eigentlich alle vom Datentyo double sein und nicht von Datentyp int. Doch der Compiler ist hier gutmütig, verzeiht und wandelt int in double um. Stichwort: "Parameterübergabe und Konvertierung" am Schluss dieser Präsentation.

41 public class MainVererbung1{ public static void main(String[] args){
Modell m = new Modell(10,20); Gmodell g = new Gmodell(2,3,4); double a,b,c,f,v; // ... } Adresse Wert ... 0420 l=10 b=20 Was ist m ? Was geschieht im Arbeitsspeicher? m Im Arbeitsspeicher wird "irgendwo" Speicher für ein Objekt reserviert, auf das m zeigt. Dieses Objekt besteht aus 2 "Schubladen" l und b und wird durch den zweiparametrigen Konstruktor Modell vorbelegt

42 public class MainVererbung1{ public static void main(String[] args){
Modell m = new Modell(10,20); Gmodell g = new Gmodell(2,3,4); double a,b,c,f,v; // ... } Adresse Wert ... 0420 l=10 b=20 Was ist g ? Was geschieht im Arbeitsspeicher? m Im Arbeitsspeicher wird "irgendwo" Speicher für ein Objekt reserviert, auf das g zeigt. Dieses Objekt besteht aus 3 "Schubladen" l, b h und wird durch den dreiparametrigen Konstruktor Gmodell vorbelegt. 0470 l=2 b=3 h=4 g

43 public class MainVererbung1{ public static void main(String[] args){
Modell m = new Modell(10,20); Gmodell g = new Gmodell(2,3,4); double a,b,c,f,v; // ... } Adresse Wert ... 0420 l=10 b=20 Gibt es einen Zusammenhang zwischen m und g ? m nein! 0470 l=2 b=3 h=4 g

44 public class MainVererbung1{ public static void main(String[] args){
Die Methode gibt es nicht in der Klasse Modell public class MainVererbung1{ public static void main(String[] args){ Modell m = new Modell(10,20); Gmodell g = new Gmodell(2,3,4); double a,b,c,f,v; a = m.getL(); b = m.getB(); c = m.getH(); f = m.getFlaeche(); v = m.getVolumen(); a = g.getL(); b = g.getB(); c = g.getH(); f = g.getFlaeche(); v = g.getVolumen(); } Die Methode gibt es nicht in der Klasse Modell Was bewirken die folgenden Anweisungen? // a=10 // b=20 // Fehler !! // f=200 // Fehler !! // a=2 // b=3 // c=4 // f=6 // v=24

45 Verdeckte Member

46 class Gmodell extends Modell{ private double h;
public Gmodell(double pl, double pb, double ph){... public void setH(double ph){... public double getH(){... public double getVolumen(){... public double getFlaeche(){... } Alles gleich wie vorher außer, daß eine Methode gleichen Namens wie in der Basisklasse existiert, die die Oberfläche des Modells (Quaders) berechnet. Wie muss sie implementiert werden ?

47 return(2*(getL()*getB()+getL()*h +getB()*h)); }
double getFlaeche(){ return(2*(getL()*getB()+getL()*h +getB()*h)); } Warum ist diese Lösung falsch ? Die Member b und l gibt es zwar in der Klasse GModell (sie wurden vererbt). Allerdings sind sie private. Auf vererbte private-Member kann weder innerhalb noch außerhalb der Klasse zugegriffen werden. double getFlaeche(){ return(2*(l*b+l*h+b*h)); }

48 public class MainVererbung1{ public static void main(String[] args){
Es wird auf die Methode der Unterklasse und nicht der Oberklasse zugegriffen, weil die Methode der Oberklasse durch die Methode der Unterklasse verdeckt wird. public class MainVererbung1{ public static void main(String[] args){ double f; Gmodell g = new Gmodell(2,3,4); f = g.getFlaeche(); } // f=52 // 52=2(2*3+2*4+3*4) Von welcher Klasse (Modell oder Gmodell) wird diese Methode aufgerufen ?

49 public class MainVererbung1{ public static void main(String[] args){
Merke: Wenn die Methode in mehreren Klassen einer Vererbungshierarchie vorkommt, wird auf die in der Vererbungshierarchie am weitesten unten stehende Methode zugegriffen. Also: public class MainVererbung1{ public static void main(String[] args){ double f; Gmodell g = new Gmodell(2,3,4); f = g.getFlaeche(); } Wenn die Methode in der Unterklasse und in der Oberklasse vorkommt wird auf die Methode der ... Unterklasse zugegriffen Wenn die Methode in der Unterklasse, aber nicht in der Oberklasse vorkommt wird auf die Methode ... Unterklasse zugegriffen Wenn die Methode nicht in der Unterklasse, aber in der Oberklasse vorkommt wird auf die Methode ... // f=52 Oberklasse zugegriffen // 52=2(2*3+2*4+3*4)

50 return(2*(h*getB()+h*getL()+ getL()*getB())); }
double getFlaeche(){ return(2*(h*getB()+h*getL()+ getL()*getB())); } getFlaeche könnte man auch anders implementieren ... double getFlaeche(){ double temp; temp= h*getL() + h*getB(); temp=2*(super.getFlaeche()+temp); return(temp); } Mit super ruft man die verdeckte Methode der Oberklasse auf, wobei super nicht die erste Anweisung in der Methode sein muss.

51 Der Zugriffschutz protected

52 Zuerst ein kleiner Ausflug

53 Ein package (deutsch Paket) ist ein besonderes Verzeichnis (auf der Festplatte), in dem sich eine Menge von "zusammengehörigen" Klassen (ähnlich einer Programmbibliothek) befindet. Diese Klassen sind in einer (wir haben bis jetzt immer nur eine java-Datei verwendet) oder mehreren Java-Dateien (mit der Endung "java") gespeichert. Unterhalb dieses Verzeichnisses müssen sich diese o.g. Java-Dateien befinden. Ein package wird dadurch gekennzeichnet, dass in der 1. Zeile der Bezeichner package steht, wie z.B: package myPaket;

54 Wenn der Bezeichner package nicht angegeben wird, wird automatisch (ohne Zutun des Programmierers) ein spezielles package angelegt: Das Default package Das Default package ist das aktuelle Verzeichnis. Professionelle Entwickler verwenden kein Default package (es wird davon abgeraten), weil z.B. Klassen aus anderen Packages als dem Default Package nicht auf das Default Package zugreifen können.

55 ja nein Spezifizierer in gleicher Klasse in Unterklasse mit Vererbung
in gleichem Package überall private ja nein protected public nichts angegeben AUFGABE: Machen Sie in Netbeans ein Beispiel mit: protected, in Unterklasse mit Vererbung, nicht im gleichen package ja: Zugriff möglich nein: Zugriff nicht möglich

56 Ende des Ausflugs. Weitere, ausführlichere Infos zu packages,
siehe Java-Skript auf meiner Website:

57 class Gmodell extends Modell{ private double h;
public Gmodell(double pl, double pb, double ph){ super(pl,pb); setH(ph); } public void setH(double ph){ h = ph; public double getH(){ return(h); public double getVolumen(){ return(b*l*h); Wiederholung: Warum ist diese Lösung falsch ? Die Member b und l gibt es zwar in der Klasse Gmodell (sie wurden vererbt). Allerdings sind sie private. Auf vererbte private-Member kann weder innerhalb noch außerhalb der Unterklasse zugegriffen werden.

58 class Gmodell extends Modell{ private double h;
public Gmodell(double pl, double pb, double ph){ super(pl,pb); setH(ph); } public void setH(double ph){ h = ph; public double getH(){ return(h); public double getVolumen(){ return(b*l*h); Was muss man machen, damit diese Lösung funktioniert? Eine Möglichkeit wäre, b und l der Oberklasse public zu machen. Dann könnte man auch von innerhalb einer Methode der Unterklasse auf diese vererbten Member zugreifen. Welchen Nachteil hätte dies aber? Man könnte auch von außerhalb einer Methode auf die Attribute b und l zugreifen. Das widerspricht der Philosophie der objektorientierten Programmierung.

59 class Gmodell extends Modell{ private double h;
public Gmodell(double pl, double pb, double ph){ super(pl,pb); setH(ph); } public void setH(double ph){ h = ph; public double getH(){ return(h); public double getVolumen(){ return(b*l*h); In der Oberklasse kann man den Zugriffsschutz von b und l (der bisher private war) auf protected setzen. Damit kann man auch von innerhalb einer Methode der Unterklasse auf diese vererbten Member zugreifen. Von außerhalb einer Methode kann man (bei protected) nicht mehr auf die Attribute b und l zugreifen, außer... die Klasse (hier: MainVererbung1) von der aus auf das protected - Attribut einer anderen Klasse (hier: Modell oder Gmodell) zugegriffen wird, befinden sich im gleichen Package (Default package). Da das bisher bei uns der Fall war, unterscheiden sich public und protected nicht.

60 public class MainVererbung1{ public static void main(String[] args){
Modell m = new Modell(10,20); Gmodell g = new Gmodell(2,3,4); double x1, x2; x1 = m.l; m.b = 5; x2 = g.l; g.b = 13;; } class Modell{ protected double l; protected double b; // Rest wie früher // class Gmodell wie früher Wann funktionieren diese Zugriffe von außerhalb nur? MainVererbung1, Modell oder Gmodell sind im gleichen Package.

61 Darstellung der Vererbung durch UML

62 Basisklasse Subklasse
... Attribute Methoden Attribute Methoden Pfeil bedeutet: erbt von Subklasse ... Analog zum Zugriffsschutz + (public) und – (private) bedeutet # : protected

63 Aufgabe: Stellen Sie die Klassen Modell, Gmodell und ihre Vererbungshierarchie in UML dar.

64 Modell - l: double - b: double + Modell(pl:double, pb:double) + setL(pl:double): void + setB(pb:double): void + getL():double + getB():double + getFlaeche():double Statt dem Zugriffschutz + oder - kann auch der Zugriffschutz # benutzt werden, also ... Gmodell - h: double + Gmodell(pl:double, pb:double, ph:double) + setH(ph:double): void + getH():double + getVolumen():double

65 Modell # l: double # b: double + Modell(pl:double, pb:double) + setL(pl:double): void + setB(pb:double): void + getL():double + getB():double + getFlaeche():double Gmodell - h: double + Gmodell(pl:double, pb:double, ph:double) + setH(ph:double): void + getH():double + getVolumen():double

66 Wann soll man eine Vererbung sinnvoll einsetzen ?

67 wenn die folgende Beziehung besteht: Subklasse "ist ein(e)" Basisklasse. Im Gegensatz zu einer Aggregation. Dort besteht die Beziehung "hat" bzw. "besteht aus"

68 Beispiele der Vererbung: Ein LKW ist ein Fahrzeug Eine Katze ist ein Tier Eine Tulpe ist eine Pflanze abgeleitete Klasse Basisklasse

69 Der Prozeß, um von einer Basisklasse durch Detaillierung und Konkretiserung zu einer Subklasse zu kommen, nennt man Spezialisierung. Der Prozeß, um von einer Subklasse durch Verallgemeinerung und Abstraktion zur Basisklasse zu kommen, nennt man Generalisierung.

70 Parameterübergabe und Konvertierung

71 I) Wenn eine Methode verlangt, dass ein Parameter einen primitiven Datentypen wie z.B. double haben muss, aber beim Methodenaufruf ein integer Wert benutzt wird, dann wird der "kleinere" Datentyp (hier also int) automatisch in den "größeren" Datentyp konvertiert (impliziter cast).

72 Beispiel (siehe Klasse Hund): Es soll der Hund Bello mit 10
Beispiel (siehe Klasse Hund): Es soll der Hund Bello mit 10.5 Kg Gewicht erzeugt werden. Anschließend soll dieses Gewicht auf 15 Kg abgeändert werden (Hund hat zugenommen).

73 class Hund{ // wie vorher }
public class MainKlassen1 { public static void main(String[] args){ Hund myh1; myh1=new Hund(); myh1.setName("Goldi"); myh1.setGewicht(10.5); myh1.setGewicht(15); } } class Hund{ // wie vorher } 10.5 ist ein Literal und hat den Datentyp double. Laut der Deklaration der Methode setGewicht(...) muß er auch diesen Datentyp haben. Welchen Datentyp hat dieser aufrufende (aktuelle) Parameter und welchen Datentyp müsste er laut Deklaration der Methode setGewicht(...) haben?

74 class Hund{ // wie vorher }
public class MainKlassen1 { public static void main(String[] args){ Hund myh1; myh1=new Hund(); myh1.setName("Goldi"); myh1.setGewicht(10.5); myh1.setGewicht(15); } } class Hund{ // wie vorher } Der Compiler müsste also streng genommen eine Fehlermeldung bringen .... Er macht dies allerdings nicht, sondern wandelt automatisch den „kleineren“ Datentyp integer (also konkret 15) in den „größeren“ Datentyp double (also konkret 15.0) um! 15 ist ein Literal und hat den Datentyp integer. Laut der Deklaration der Methode setGewicht(...) müsste er aber den Datentyp double haben. Welchen Datentyp hat dieser aufrufende (aktuelle) Parameter und welchen Datentyp müsste er laut Deklaration der Methode setGewicht (...) haben?

75 II) a) Wenn eine Methode verlangt, dass ein Parameter als Datentyp eine Klasse haben muss, aber beim Methodenaufruf ein Objekt einer Unterklasse davon übergeben wird, dann wird das Objekt vor der Übergabe an den Parameter automatisch in das Objekt der Oberklasse konvertiert (impliziter cast).

76 b) Umgekehrt geht es nicht: Ein Objekt einer Oberklasse kann nicht an einen Parameter einer Methode übergeben werden, die ein Objekt einer Unterklasse erwartet.

77 Beispiel (Klasse Modell und GModell wie im früheren Beispiel)

78 package parameteruebergabe1; public class MainParameter1 {
public static void main(String[] args){ Modell m = new Modell(10,20); Gmodell g = new Gmodell(2,3,4); changeLaenge(m, 20); changeLaenge(g, 40); System.out.println(m.getL()); System.out.println(g.getL()); } public static void changeLaenge( Modell pModell, double pl){ double tempLaenge; tempLaenge = pModell.getL(); pModell.setL(tempLaenge+pl); Die Methode changeLaenge verlangt den Datentyp Modell welchen Datentyp (Klasse) muß diese Variable haben und warum? Warum ist dann dieser Aufruf richtig? Warum muß hier static stehen? Dies wird später behandelt! Weil g automatisch in das Objekt von Datentyp Modell konvertiert wird.


Herunterladen ppt "Vererbung."

Ähnliche Präsentationen


Google-Anzeigen