OOP Konzept für Anfänger: Was ist Vererbung?
Vererbung ist eines der Kernkonzepte objektorientierter Programmiersprachen (OOP). Es ist ein Mechanismus, bei dem Sie eine Klasse aus einer anderen Klasse für eine Hierarchie von Klassen ableiten können, die eine Reihe von Attributen und Methoden gemeinsam nutzen.
Sie können damit verschiedene Arten von Ausnahmen deklarieren, vorhandenen Frameworks benutzerdefinierte Logik hinzufügen und sogar Ihr Domänenmodell einer Datenbank zuordnen.,
Deklarieren Sie eine Vererbungshierarchie
In Java kann jede Klasse nur von einer anderen Klasse abgeleitet werden. Diese Klasse wird als Oberklasse oder übergeordnete Klasse bezeichnet. Die abgeleitete Klasse wird Unterklasse oder untergeordnete Klasse genannt.
Sie verwenden das Schlüsselwort extends, um die Klasse zu identifizieren, die Ihre Unterklasse erweitert. Wenn Sie keine Oberklasse deklarieren, erweitert Ihre Klasse implizit das Klassenobjekt. Object ist die Wurzel aller Vererbungshierarchien; Es ist die einzige Klasse in Java, die keine andere Klasse erweitert.
Das folgende Diagramm und code-snippets zeigen ein Beispiel für eine einfache Vererbungshierarchie.,
Die Klasse BasicCoffeeMachine deklariert keine Oberklasse und erweitert implizit das Klassenobjekt. Sie können das CoffeeMachine-Beispielprojekt auf GitHub klonen.
Die Klasse PremiumCoffeeMachine ist eine Unterklasse der BasicCoffeeMachine Klasse.
Vererbungs – und Zugriffsmodifikatoren
Zugriffsmodifikatoren definieren, welche Klassen auf ein Attribut oder eine Methode zugreifen können. In einem meiner vorherigen Beiträge zur Kapselung habe ich Ihnen gezeigt, wie Sie damit einen Mechanismus zum Ausblenden von Informationen implementieren können. Dies ist jedoch nicht der einzige Fall, in dem Sie mit den verschiedenen Modifikatoren vertraut sein müssen., Sie wirken sich auch auf die Entitäten und Attribute aus, auf die Sie innerhalb einer Vererbungshierarchie zugreifen können.
Hier ist ein kurzer Überblick über die verschiedenen Modifikatoren:
- Auf private Attribute oder Methoden kann nur innerhalb derselben Klasse zugegriffen werden.
- Attribute und Methoden ohne Zugriffsmodifikator können innerhalb derselben Klasse und von allen anderen Klassen innerhalb desselben Pakets aufgerufen werden.
- Auf geschützte Attribute oder Methoden kann innerhalb derselben Klasse, von allen Klassen innerhalb desselben Pakets und von allen Unterklassen zugegriffen werden.,
- Auf öffentliche Attribute und Methoden können alle Klassen zugreifen.
Wie Sie in dieser Liste sehen können, kann eine Unterklasse auf alle geschützten und öffentlichen Attribute und Methoden der Oberklasse zugreifen. Wenn die Unterklasse und die Oberklasse zum selben Paket gehören, kann die Unterklasse auch auf alle paketprivaten Attribute und Methoden der Oberklasse zugreifen.
Ich mache das zweimal im Konstruktor der PremiumCoffeeMachine Klasse.
Ich benutze zuerst das Schlüsselwort super, um den Konstruktor der Oberklasse aufzurufen. Der Konstruktor ist öffentlich und die Unterklasse kann darauf zugreifen., Das Schlüsselwort super verweist auf die Oberklasse. Sie können damit auf ein Attribut zugreifen oder eine Methode der Oberklasse aufrufen, die von der aktuellen Unterklasse überschrieben wird. Aber mehr dazu im folgenden Abschnitt.
Das geschützte Attribut ConfigMap wird von der BasicCoffeeMachine Klasse definiert. Durch die Erweiterung dieser Klasse wird das Attribut auch Teil der PremiumCoffeeMachine-Klasse, und ich kann die Konfiguration hinzufügen, die erforderlich ist, um der Karte einen Espresso zuzubereiten.,
Methode Überschreiben
Vererbung fügt Ihrer Unterklasse nicht nur alle öffentlichen und geschützten Methoden der Oberklasse hinzu, sondern ermöglicht Ihnen auch, deren Implementierung zu ersetzen. Die Methode der Unterklasse überschreibt dann die der Oberklasse. Dieser Mechanismus wird Polymorphismus genannt.
Ich verwende das in der PremiumCoffeeMachine-Klasse, um die Kaffeebrühfunktionen der Kaffeemaschine zu erweitern. Die brewCoffee-Methode der BasicCoffeeMachine-Methode kann nur Filterkaffee brauen.
Ich überschreibe diese Methode in der PremiumCoffeeMachine-Klasse, um Unterstützung für die CoffeeSelection hinzuzufügen.,ESPRESSO. Wie Sie im Code-Snippet sehen können, ist das Super-Schlüsselwort sehr hilfreich, wenn Sie eine Methode überschreiben. Die brewCoffee-Methode der BasicCoffeeMachine übernimmt bereits die CoffeeSelection.FILTER_COFFEE und löst eine CoffeeException für nicht unterstützte CoffeeSelections aus.
Ich kann das in meiner neuen brewCoffee-Methode wiederverwenden. Anstatt dieselbe Logik neu zu implementieren, überprüfe ich nur, ob die CoffeeSelection korrekt ist. Wenn dies nicht der Fall ist, verwende ich das super-Schlüsselwort, um die brewCoffee-Methode der Oberklasse aufzurufen.,
Verhindern, dass eine Methode überschrieben wird
Wenn Sie sicherstellen möchten, dass keine Unterklasse die Implementierung einer Methode ändern kann, können Sie sie als endgültig deklarieren. In diesem Beispiel habe ich das für die addBeans-Methode der BasicCoffeeMachine-Klasse getan.
Es ist oft eine gute Idee, alle Methoden endgültig zu machen, die von einem Konstruktor aufgerufen werden. Es verhindert, dass eine Unterklasse das Verhalten des Konstruktors oft unbeabsichtigt ändert.,
Eine Unterklasse ist auch vom Typ ihrer Oberklasse
Eine Unterklasse erbt nicht nur die Attribute und Methoden der Oberklasse, sondern auch die Typen der Oberklasse. Im Beispiel ist die BasicCoffeeMachine vom Typ BasicCoffeeMachine und Object. Und ein PremiumCoffeeMachine-Objekt hat die Typen PremiumCoffeeMachine, BasicCoffeeMachine und Object.
Aus diesem Grund können Sie ein PremiumCoffeeMachine-Objekt in den Typ BasicCoffeeMachine umwandeln.
BasicCoffeeMachinee coffeeMachine = (BasicCoffeeMachine) PremiumCoffeeMachine(beans);
Damit können Sie Code schreiben, der die Oberklasse verwendet, und ihn mit allen Unterklassen ausführen.,
In diesem Beispiel wird der Code der createCoffeeMachine Methode zurückgegeben und die makeCoffee Methode verwendet die BasicCoffeeMachine Klasse. Die createCoffeeMachine-Methode instanziiert jedoch ein neues PremiumCoffeeMachine-Objekt. Wenn es von der Methode zurückgegeben wird, wird das Objekt automatisch in BasicCoffeeMachine und der Code kann alle öffentlichen Methoden der BasicCoffeeMachine Klasse aufrufen.
Das coffeeMachine-Objekt wird in BasicCoffeeMachine, aber es ist immer noch eine PremiumCoffeeMachine., Wenn die makeCoffee-Methode die brewCoffee-Methode aufruft, ruft sie die überschriebene Methode in der PremiumCoffeeMachine-Klasse auf.
Definieren abstrakter Klassen
Abstrakte Klassen unterscheiden sich von den anderen Klassen, über die wir gesprochen haben. Sie können erweitert, aber nicht instanziiert werden. Dies macht sie ideal, um konzeptionelle Verallgemeinerungen darzustellen, die in Ihrer spezifischen Domäne nicht vorhanden sind, es Ihnen jedoch ermöglichen, Teile Ihres Codes wiederzuverwenden.
Mit dem Schlüsselwort abstract deklarieren Sie eine Klasse oder Methode als abstrakt. Eine abstrakte Klasse muss keine abstrakten Methoden enthalten., Eine abstrakte Methode muss jedoch von einer abstrakten Klasse deklariert werden.
Lassen Sie uns das Beispiel Kaffeemaschine umgestalten und die AbstractCoffeeMachine Klasse als Oberklasse der BasicCoffeeMachine Klasse einführen. Ich deklariere diese Klasse als abstrakt und definiere die abstrakte brewCoffee-Methode.
public abstract class AbstractCoffeeMachine { protected Map<CoffeeSelection, Configuration> configMap; public AbstractCoffeeMachine() { this.configMap = new HashMap<CoffeeSelection, Configuration>(); } public abstract Coffee brewCoffee(CoffeeSelection selection) throws CoffeeException; }
Wie Sie sehen, stelle ich den Hauptteil der abstrakten brewCoffee-Methode nicht zur Verfügung. Ich erkläre es einfach so, wie ich es in einer Schnittstelle tun würde., Wenn Sie die AbstractCoffeeMachine-Klasse erweitern, müssen Sie die Unterklasse als abstrakt definieren oder die brewCoffee-Methode überschreiben, um den Methodentext zu implementieren.
Ich mache einige kleinere Änderungen an der BasicCoffeeMachine Klasse. Es erweitert jetzt die AbstractCoffeeMachine-Klasse, und die bereits vorhandene brewCoffee-Methode überschreibt die abstrakte Methode der Oberklasse.
eine Andere Sache, die ich geändert habe, ist der Konstruktor der BasicCoffeeMachine Klasse. Es ruft jetzt den Konstruktor der Oberklasse auf und fügt dem ConfigMap Attribut ein Schlüssel-Wert-Paar hinzu, ohne die Map zu instanziieren., Es wird von der abstrakten Oberklasse definiert und instanziiert und kann in allen Unterklassen verwendet werden.
Dies ist einer der Hauptunterschiede zwischen einer abstrakten Oberklasse und einer Schnittstelle. Mit der abstract Klasse können Sie nicht nur Methoden deklarieren, sondern auch Attribute definieren, die nicht statisch und endgültig sind.
Zusammenfassung
Wie Sie gesehen haben, ist Vererbung ein leistungsfähiges Konzept, mit dem Sie eine Unterklasse implementieren können, die eine Oberklasse erweitert. Auf diese Weise erbt die Unterklasse alle geschützten und öffentlichen Attribute und Methoden sowie die Typen der Oberklasse., Sie können dann die geerbten Attribute der Oberklasse verwenden, die geerbten Methoden verwenden oder überschreiben und die Unterklasse in einen beliebigen Typ ihrer Oberklasse umwandeln.
Sie können eine abstrakte Klasse verwenden, um eine allgemeine Abstraktion zu definieren, die nicht instanziiert werden kann. Innerhalb dieser Klasse können Sie abstrakte Methoden deklarieren, die von nicht abstrakten Unterklassen überschrieben werden müssen. Dies wird häufig verwendet, wenn die Implementierung dieser Methode für jede Unterklasse spezifisch ist, Sie jedoch eine allgemeine API für alle Klassen der Hierarchie definieren möchten.