Komposition vs Vererbung ist eine der häufig gestellten Interviewfragen. Sie haben sicher auch schon gehört, dass man Komposition anstelle von Vererbung verwenden sollte.
Komposition vs Vererbung
Sowohl Komposition als auch Vererbung sind Konzepte der objektorientierten Programmierung. Sie sind nicht an eine bestimmte Programmiersprache wie Java gebunden. Bevor wir programmatisch Komposition über Vererbung vergleichen, lassen Sie uns eine schnelle Definition von ihnen haben.
Komposition
Komposition ist die Design-Technik in der objektorientierten Programmierung, um eine hat-eine-Beziehung zwischen Objekten zu implementieren. Komposition in Java wird erreicht, indem Instanzvariablen anderer Objekte verwendet werden. Zum Beispiel wird eine Person, die einen Job hat, in der objektorientierten Java-Programmierung wie folgt implementiert:
package com.journaldev.composition;
public class Job {
// Variablen, Methoden usw.
}
package com.journaldev.composition;
public class Person {
//Komposition hat-eine-Beziehung
private Job job;
//Variablen, Methoden, Konstruktoren usw. objektorientiert
Vererbung
Vererbung ist die Entwurfstechnik in der objektorientierten Programmierung zur Implementierung der ist-ein-Beziehung zwischen Objekten. Vererbung in Java wird mit dem extends-Schlüsselwort umgesetzt. Zum Beispiel wird die Beziehung „Katze ist ein Tier“ in der Java-Programmierung wie folgt implementiert:
package com.journaldev.inheritance;
public class Animal {
// Variablen, Methoden usw.
}
package com.journaldev.inheritance;
public class Cat extends Animal{
}
Komposition über Vererbung
Sowohl Komposition als auch Vererbung fördern die Code-Wiederverwendung auf unterschiedliche Weise. Also, welche Methode soll man wählen? Wie vergleicht man Komposition und Vererbung? Du hast vielleicht gehört, dass in der Programmierung die Bevorzugung von Komposition gegenüber Vererbung empfohlen wird. Schauen wir uns einige Gründe an, die dir bei der Entscheidung zwischen Komposition und Vererbung helfen werden.
-
Vererbung ist eng gekoppelt, während Komposition lose gekoppelt ist. Nehmen wir an, wir haben unten stehende Klassen mit Vererbung.
Paket com.journaldev.java.Beispiele; public class KlasseA { public void foo(){ } } Klasse KlasseB erweitert KlasseA{ public void bar(){ } }
Zur Vereinfachung haben wir sowohl die Superklasse als auch die Unterklasse in einem einzigen Paket. In der Regel befinden sie sich jedoch in separaten Codebasen. Es könnten viele Klassen sein, die die Superklasse KlasseA erweitern. Ein sehr häufiges Beispiel für diese Situation ist die Erweiterung der Exception-Klasse. Nehmen wir nun an, dass die Implementierung von KlasseA wie folgt geändert wird und eine neue Methode bar() hinzugefügt wird.
Paket com.journaldev.java.Beispiele; public class KlasseA { public void foo(){ } public int bar(){ return 0; } }
Sobald Sie die neue Implementierung von KlasseA verwenden, erhalten Sie einen Kompilierungsfehler in KlasseB mit dem Text
Der Rückgabetyp ist mit ClassA.bar() nicht kompatibel
. Die Lösung wäre, entweder die Methode bar() in der Superklasse oder in der Unterklasse zu ändern, um sie kompatibel zu machen. Wenn Sie anstelle von Vererbung die Komposition verwendet hätten, würden Sie dieses Problem nie haben. Ein einfaches Beispiel für die Implementierung von KlasseB mit Komposition könnte wie folgt aussehen.Klasse KlasseB{ KlasseA klasseA = new KlasseA(); public void bar(){ klasseA.foo(); klasseA.bar(); } }
-
Bei der Vererbung gibt es keine Zugriffskontrolle, während der Zugriff bei der Komposition eingeschränkt werden kann. Wir stellen alle Methoden der Superklasse den anderen Klassen zur Verfügung, die Zugriff auf die Unterklasse haben. Wenn also eine neue Methode eingeführt wird oder Sicherheitslücken in der Superklasse vorhanden sind, wird die Unterklasse angreifbar. Da wir bei der Komposition auswählen können, welche Methoden verwendet werden, ist sie sicherer als Vererbung. Zum Beispiel können wir die Methode foo() von ClassA für andere Klassen mit folgendem Code in ClassB zugänglich machen.
class ClassB { ClassA classA = new ClassA(); public void foo(){ classA.foo(); } public void bar(){ } }
Dies ist einer der Hauptvorteile der Komposition gegenüber der Vererbung.
-
Die Komposition bietet Flexibilität bei der Aufruf von Methoden, die bei Szenarien mit mehreren Unterklassen nützlich ist. Angenommen, wir haben das folgende Vererbungsszenario.
abstrakte Klasse Abs { abstrakte void foo(); } public class ClassA erweitert Abs{ public void foo(){ } } Klasse ClassB erweitert Abs{ public void foo(){ } } Klasse Test { ClassA a = new ClassA(); ClassB b = new ClassB(); public void test(){ a.foo(); b.foo(); } }
Was ist, wenn es mehr Unterklassen gibt? Macht die Komposition unseren Code hässlich, indem wir eine Instanz für jede Unterklasse haben? Nein, wir können die Testklasse wie folgt umschreiben.
Klasse Test { Abs obj = null; Test1(Abs o){ this.obj = o; } public void foo(){ this.obj.foo(); } }
Dies gibt Ihnen die Flexibilität, jede Unterklasse je nach im Konstruktor verwendeten Objekt zu verwenden.
-
Ein weiterer Vorteil der Komposition gegenüber der Vererbung ist der Testumfang. Die Einheitstestung ist bei der Komposition einfach, da wir wissen, welche Methoden wir von einer anderen Klasse verwenden. Wir können es für Tests simulieren, während wir bei der Vererbung stark von der Superklasse abhängen und nicht wissen, welche Methoden der Superklasse verwendet werden. Daher müssen wir alle Methoden der Superklasse testen. Dies ist zusätzliche Arbeit und wir müssen sie unnötigerweise aufgrund der Vererbung erledigen.
Das war’s mit Komposition gegenüber Vererbung. Sie haben genug Gründe, sich für Komposition anstelle von Vererbung zu entscheiden. Verwenden Sie Vererbung nur, wenn Sie sicher sind, dass die Superklasse nicht geändert wird, andernfalls entscheiden Sie sich für Komposition.
Source:
https://www.digitalocean.com/community/tutorials/composition-vs-inheritance