Compositie versus Overerving is een van de veelgestelde vragen tijdens sollicitatiegesprekken. Je hebt waarschijnlijk ook gehoord dat je Compositie moet gebruiken in plaats van Overerving.
Compositie versus Overerving
Zowel compositie als overerving zijn concepten in objectgeoriënteerd programmeren. Ze zijn niet specifiek gebonden aan een bepaalde programmeertaal, zoals Java. Voordat we compositie boven overerving programmatisch vergelijken, laten we eerst een korte definitie geven.
Compositie
Compositie is een ontwerptechniek in objectgeoriënteerd programmeren om de “heeft-een” relatie tussen objecten te implementeren. In Java wordt compositie bereikt door het gebruik van instantievariabelen van andere objecten. Bijvoorbeeld, een persoon die een baan heeft wordt als volgt geïmplementeerd in objectgeoriënteerd programmeren in Java.
package com.journaldev.composition;
public class Job {
// variabelen, methoden, enz.
}
package com.journaldev.composition;
public class Person {
// compositie "heeft-een" relatie
private Job job;
// variabelen, methoden, constructors, enz. objectgeoriënteerd
Overerving
Overerving is de ontwerptechniek in objectgeoriënteerd programmeren om de is-een-relatie tussen objecten te implementeren. Overerving in Java wordt geïmplementeerd met het extends-sleutelwoord. Bijvoorbeeld, de relatie “Kat is een Dier” in Java-programmering zou worden geïmplementeerd zoals hieronder aangegeven.
package com.journaldev.inheritance;
public class Animal {
// variabelen, methoden, enz.
}
package com.journaldev.inheritance;
public class Cat extends Animal{
}
Compositie boven overerving
Zowel compositie als overerving bevorderen hergebruik van code via verschillende benaderingen. Dus welke te kiezen? Hoe compositie vergelijken met overerving. Je hebt waarschijnlijk gehoord dat je in programmeren de voorkeur moet geven aan compositie boven overerving. Laten we enkele redenen bekijken die je zullen helpen bij het kiezen tussen compositie en overerving.
-
Overerving is sterk gekoppeld terwijl compositie losjes gekoppeld is. Laten we aannemen dat we hieronder klassen hebben met overerving.
package com.journaldev.java.examples; public class ClassA { public void foo(){ } } class ClassB extends ClassA{ public void bar(){ } }
Voor de eenvoud hebben we zowel de superklasse als de subklasse in een enkel pakket. Maar meestal zullen ze in afzonderlijke codebases zijn. Er kunnen veel klassen zijn die de superklasse ClassA uitbreiden. Een zeer gebruikelijk voorbeeld van deze situatie is het uitbreiden van de Exception-klasse. Laten we nu zeggen dat de implementatie van ClassA is gewijzigd zoals hieronder, er is een nieuwe methode bar() toegevoegd.
package com.journaldev.java.examples; public class ClassA { public void foo(){ } public int bar(){ return 0; } }
Zodra u begint met het gebruik van de nieuwe implementatie van ClassA, krijgt u een compileerfout in ClassB als
Het retourtype is onverenigbaar met ClassA.bar()
. De oplossing zou zijn om ofwel de superklasse of de subklasse bar() methode te wijzigen om ze compatibel te maken. Als u Compositie in plaats van overerving had gebruikt, zou u dit probleem nooit hebben gehad. Een eenvoudig voorbeeld van de implementatie van ClassB met behulp van Compositie kan als volgt zijn.class ClassB{ ClassA classA = new ClassA(); public void bar(){ classA.foo(); classA.bar(); } }
-
Er is geen toegangscontrole in overerving, terwijl toegang kan worden beperkt in compositie. We stellen alle methoden van de superklasse bloot aan de andere klassen die toegang hebben tot de subklasse. Dus als er een nieuwe methode wordt geïntroduceerd of er zijn beveiligingslekken in de superklasse, wordt de subklasse kwetsbaar. Aangezien we bij compositie kiezen welke methoden we gebruiken, is het veiliger dan overerving. Bijvoorbeeld, we kunnen de blootstelling van de methode ClassA foo() aan andere klassen mogelijk maken met de onderstaande code in ClassB.
class ClassB { ClassA classA = new ClassA(); public void foo(){ classA.foo(); } public void bar(){ } }
Dit is een van de belangrijke voordelen van compositie boven overerving.
-
Compositie biedt flexibiliteit bij het oproepen van methoden die nuttig is bij scenario’s met meerdere subklassen. Laten we bijvoorbeeld het volgende overervingsscenario bekijken.
abstract class Abs { abstract void foo(); } public class ClassA extends Abs{ public void foo(){ } } class ClassB extends Abs{ public void foo(){ } } class Test { ClassA a = new ClassA(); ClassB b = new ClassB(); public void test(){ a.foo(); b.foo(); } }
Dus wat als er meer subklassen zijn, maakt compositie onze code dan lelijk door één instantie voor elke subklasse te hebben? Nee, we kunnen de Test-klasse herschrijven zoals hieronder.
class Test { Abs obj = null; Test1(Abs o){ this.obj = o; } public void foo(){ this.obj.foo(); } }
Dit geeft je de flexibiliteit om elke subklasse te gebruiken op basis van het object dat in de constructor wordt gebruikt.
-
Nog een voordeel van compositie boven overerving is de testomvang. Unit testing is eenvoudig bij compositie omdat we weten welke methoden we gebruiken vanuit een andere klasse. We kunnen het nabootsen voor testen, terwijl we bij overerving sterk afhankelijk zijn van de superklasse en niet weten welke methoden van de superklasse zullen worden gebruikt. Dus we moeten alle methoden van de superklasse testen. Dit is extra werk en we moeten het onnodig doen vanwege overerving.
Dat is alles voor compositie versus overerving. Je hebt genoeg redenen om compositie boven overerving te kiezen. Gebruik overerving alleen als je zeker weet dat de superklasse niet zal veranderen, ga anders voor compositie.
Source:
https://www.digitalocean.com/community/tutorials/composition-vs-inheritance