Kapitel 9: Vererbung: Unterschied zwischen den Versionen
(Die Seite wurde neu angelegt: „Die Vererbung ist eines der grundlegenden Konzepte der Objektorientierung. Sie dient dazu, aufbauend auf bereits existierenden Klassen neue zu schaffen, wobei …“) |
|||
Zeile 34: | Zeile 34: | ||
<big>[[Aufgaben 9.1.]]</big> | <big>[[Aufgaben 9.1.]]</big> | ||
+ | |||
+ | |||
+ | |||
+ | '''Umsetzung in Java''' | ||
+ | |||
+ | In Java können Klassenhierarchien nur durch Spezialisierung gebildet werden: Unterklasse erweitert (''extends'') Oberklasse. Dies spiegelt sich in der Syntax wieder - die Klassendefinition der Unterklasse weist auf ihren Status als Erweiterung der Oberklasse hin: | ||
+ | |||
+ | <pre> | ||
+ | public class <Name der Unterklasse> extends <Name der Oberklasse> | ||
+ | </pre> | ||
+ | |||
+ | <u>Hinweise:</u> | ||
+ | |||
+ | * Vererbung bedeutet, dass die Unterklasse alle Attribute und Methoden von der Oberklasse übernimmt. | ||
+ | * Es werden keine Konstruktoren vererbt! | ||
+ | * Unter- und Oberklasse bieten Konstruktoren an. | ||
+ | * Die Unterklasse kümmert sich in ihrem Konstruktor nur um die Attribute, die in der Unterklasse definiert sind. | ||
+ | * Damit auch die Datenfelder der Oberklasse korrekt initialisiert werden,rufen wir den Konstruktor der Oberklasse auf. | ||
+ | * Der Aufruf des Konstruktors der Oberklasse erfolgt mit dem Schlüsselwort '''super'''. | ||
+ | * Dieser Aufruf muss stets die erste Anweisung in einem Konstruktor der Unterklasse sein! Ansonsten fügt der Compiler den Aufruf eines parameterlosen Konstruktors für die Oberklasse ein. | ||
+ | |||
+ | Als Beispiel soll nun die (teilweise) Implementierung der Klassenhierarchie aus dem Schulfamilie-Beispiel dienen: | ||
+ | |||
+ | |||
+ | <syntaxhighlight lang="java"> | ||
+ | |||
+ | public class Person { | ||
+ | //Attribute | ||
+ | private String name; | ||
+ | private String geburtsdatum | ||
+ | |||
+ | //Konstruktor | ||
+ | public person(String name, String geburtsdatum){ | ||
+ | this.name=name; | ||
+ | this.geburtsdatum = geburtsdatum; | ||
+ | } | ||
+ | |||
+ | //Getter- und Setter-Methoden | ||
+ | public String getName(){ | ||
+ | return name; | ||
+ | } | ||
+ | |||
+ | public String getGeburtsdatum(){ | ||
+ | return geburtsdatum; | ||
+ | } | ||
+ | |||
+ | public void setName(String n){ | ||
+ | name=n; | ||
+ | } | ||
+ | |||
+ | public void setGeburtsdatum(String g){ | ||
+ | geburtsdatum = g; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | public class MdS extends Person{ | ||
+ | //weitere Attribute für Mitglieder der Schulfamilie | ||
+ | public String telefonnummer; | ||
+ | |||
+ | //Konstruktor | ||
+ | public MdS(String name, String geburtsdatum, String telefonnummer){ | ||
+ | //Aufruf des Konstruktors der Oberklasse | ||
+ | super(name, geburtsdatum); | ||
+ | //Initialisierung der weiteren Variablen | ||
+ | this.telefonnummer=telefonnummer; | ||
+ | } | ||
+ | |||
+ | //weitere Getter- und Setter-Methoden | ||
+ | public String getTelefonnummer(){ | ||
+ | return telefonnummer; | ||
+ | } | ||
+ | |||
+ | public void setTelefonnummer(String t){ | ||
+ | telefonnummer=t; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | public class Lehrer extends MdS{ | ||
+ | //weitere Attribute | ||
+ | private String pkz; | ||
+ | ... | ||
+ | |||
+ | //Konstruktor | ||
+ | public Lehrer(String name, String geburtsdatum, String telefonnummer, String pkz){ | ||
+ | //Aufruf des Konstruktors der Oberklasse | ||
+ | super(name, geburtsdatum, telefonnummer); | ||
+ | //Initialisierung der weiteren Variablen | ||
+ | this.pkz = pkz; | ||
+ | } | ||
+ | |||
+ | //Getter-, Setter- und andere Methoden | ||
+ | ... | ||
+ | |||
+ | public void pruefen (Schueler s){ ... } | ||
+ | |||
+ | public void verweisErteilen /Schueler s) { ... } | ||
+ | |||
+ | ... | ||
+ | } | ||
+ | |||
+ | |||
+ | public class Schueler extends MdS { | ||
+ | //weitere Attribute | ||
+ | private String schueler-ID; | ||
+ | |||
+ | //Konstruktor | ||
+ | public Schueler((String name, String geburtsdatum, String telefonnummer, String schueler-ID){ | ||
+ | //Aufruf des Konstruktors der Oberklasse | ||
+ | super(name, geburtsdatum, telefonnummer); | ||
+ | //Initialisierung der weiteren Variablen | ||
+ | this.schueler-ID = schueler-ID; | ||
+ | } | ||
+ | |||
+ | //Getter-, Setter- und andere Methoden | ||
+ | ... | ||
+ | |||
+ | public void hausaufgabeMachen(){ ... } | ||
+ | |||
+ | public void rechenschaftsablage(){ ... } | ||
+ | |||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | <u>Zur Vertiefung: </u> | ||
+ | |||
+ | <div style="margin-left:100px; margin-top:30px; margin-bottom:30px"> | ||
+ | {{#ev:youtube|Zf-aL6gCPxQ}} | ||
+ | </div> | ||
+ | |||
+ | |||
+ | <big>[[Aufgaben 9.2.]]</big> |
Version vom 25. Mai 2014, 16:45 Uhr
Die Vererbung ist eines der grundlegenden Konzepte der Objektorientierung. Sie dient dazu, aufbauend auf bereits existierenden Klassen neue zu schaffen, wobei die Beziehung zwischen ursprünglicher und neuer Klasse - anders als bei einer Assoziation - dauerhaft ist. Eine neue Klasse kann dabei eine Erweiterung oder eine Einschränkung der ursprünglichen Klasse sein.
Die vererbende Klasse wird meist Oberklasse (oder auch Superklasse) genannt, die erbende Unterklasse.
Problemstellung
Ein Autohändler, der sowohl mit Neu- als auch mit Gebrauchtwagen handelt, will die Fahrzeuge in einer Datenbank erfassen, wobei er die beiden Typen möglichst effizient und unabhängig voneinander abspeichern möchte. Eine Modellierung könnte zuerst einmal folgendermaßen aussehen:
Was hier sehr schnell auffallen dürfte, ist die Tatsache, dass die Darstellungen weitgehend übereinstimmen und der Gebrauchtwagen nur weitere Attribute enthält, die beim Neuwagen von geringem Interesse sind. Das Konzept der Vererbung ermöglicht es nun, die Klasse Gebrauchtwagen als Unterklasse der Klasse Auto zu modellieren. Dies bedeutet, dass ein Objekt alle Attribute und Methoden der Oberklasse erbt und noch weitere Attribute und Methoden erhält. In der Unified Modeling Language (UML) wird eine Vererbungsbeziehung durch einen Pfeil mit einer dreieckigen Spitze dargestellt, der von der Unterklasse zur Oberklasse zeigt. Geerbte Attribute und Methoden werden in der Darstellung der Unterklasse nicht wiederholt.
Spezialisierung und Generalisierung
Spezialisierung und Generalisierung sind zwei Sichtweisen des Vererbungskonzepts. Bilden wir eine neue Klasse, deren Instanzen eine Teilmenge der Instanzen der Oberklasse darstellen, sprechen wir bei der Bildung der Unterklasse von einer Spezialisierung (Konkretisierung). Fassen wir dagegen Attribute und Methoden mehrerer ähnlicher Klassen zu einer neuen Klasse zusammen, sprechen wir von einer Generalisierung (Abstraktion).
Klassenhierarchien
In einer Klassenhierarchie werden statische Beziehungen zwischen den Klassen dargestellt. Die Darstellung ähnelt einem Stammbaum, wie wir ihn in der 6.Klasse kennengelernt haben. Die höher liegenden Klassen vererben bei Bedarf an die darunterliegenden Klassen welche wieder an Klassen unter ihnen vererben.
Beispiel:
Die Schulfamilie hat verschiedene Mitglieder. Es gibt Schüler, Lehrer und Eltern, die alle nicht nur Mitglieder der Schulfamilie (MdS) sind, sondern sie alle sind Personen. Alle Mitglieder der Schulfamilie erben von der Klasse Person die Attribute name und geburtsdatum. Lehrer und Schüler haben dagegen weitere recht unterschiedliche Attribute. Mitglieder der Schulleitung sind zwar auch Lehrer, haben aber noch weitere Attribute, was eine Spezialisierung der Klasse Lehrer nahelegt.
Umsetzung in Java
In Java können Klassenhierarchien nur durch Spezialisierung gebildet werden: Unterklasse erweitert (extends) Oberklasse. Dies spiegelt sich in der Syntax wieder - die Klassendefinition der Unterklasse weist auf ihren Status als Erweiterung der Oberklasse hin:
public class <Name der Unterklasse> extends <Name der Oberklasse>
Hinweise:
- Vererbung bedeutet, dass die Unterklasse alle Attribute und Methoden von der Oberklasse übernimmt.
- Es werden keine Konstruktoren vererbt!
- Unter- und Oberklasse bieten Konstruktoren an.
- Die Unterklasse kümmert sich in ihrem Konstruktor nur um die Attribute, die in der Unterklasse definiert sind.
- Damit auch die Datenfelder der Oberklasse korrekt initialisiert werden,rufen wir den Konstruktor der Oberklasse auf.
- Der Aufruf des Konstruktors der Oberklasse erfolgt mit dem Schlüsselwort super.
- Dieser Aufruf muss stets die erste Anweisung in einem Konstruktor der Unterklasse sein! Ansonsten fügt der Compiler den Aufruf eines parameterlosen Konstruktors für die Oberklasse ein.
Als Beispiel soll nun die (teilweise) Implementierung der Klassenhierarchie aus dem Schulfamilie-Beispiel dienen:
public class Person { //Attribute private String name; private String geburtsdatum //Konstruktor public person(String name, String geburtsdatum){ this.name=name; this.geburtsdatum = geburtsdatum; } //Getter- und Setter-Methoden public String getName(){ return name; } public String getGeburtsdatum(){ return geburtsdatum; } public void setName(String n){ name=n; } public void setGeburtsdatum(String g){ geburtsdatum = g; } } public class MdS extends Person{ //weitere Attribute für Mitglieder der Schulfamilie public String telefonnummer; //Konstruktor public MdS(String name, String geburtsdatum, String telefonnummer){ //Aufruf des Konstruktors der Oberklasse super(name, geburtsdatum); //Initialisierung der weiteren Variablen this.telefonnummer=telefonnummer; } //weitere Getter- und Setter-Methoden public String getTelefonnummer(){ return telefonnummer; } public void setTelefonnummer(String t){ telefonnummer=t; } } public class Lehrer extends MdS{ //weitere Attribute private String pkz; ... //Konstruktor public Lehrer(String name, String geburtsdatum, String telefonnummer, String pkz){ //Aufruf des Konstruktors der Oberklasse super(name, geburtsdatum, telefonnummer); //Initialisierung der weiteren Variablen this.pkz = pkz; } //Getter-, Setter- und andere Methoden ... public void pruefen (Schueler s){ ... } public void verweisErteilen /Schueler s) { ... } ... } public class Schueler extends MdS { //weitere Attribute private String schueler-ID; //Konstruktor public Schueler((String name, String geburtsdatum, String telefonnummer, String schueler-ID){ //Aufruf des Konstruktors der Oberklasse super(name, geburtsdatum, telefonnummer); //Initialisierung der weiteren Variablen this.schueler-ID = schueler-ID; } //Getter-, Setter- und andere Methoden ... public void hausaufgabeMachen(){ ... } public void rechenschaftsablage(){ ... } }
Zur Vertiefung: