Articles

OOP Concept voor Beginners: Wat is overerving?

overerving is een van de kernbegrippen van objectgeoriënteerde programmeertalen (OOP). Het is een mechanisme waarmee je een klasse kunt afleiden uit een andere klasse voor een hiërarchie van klassen die een set attributen en methoden delen.

u kunt het gebruiken om verschillende soorten uitzonderingen te verklaren, aangepaste logica toe te voegen aan bestaande frameworks, en zelfs uw domeinmodel toe te wijzen aan een database.,

declareren Een overerving hiërarchie

in Java kan elke klasse alleen worden afgeleid van een andere klasse. Die klasse wordt een superklasse of ouderklasse genoemd. De afgeleide klasse wordt subklasse of kindklasse genoemd.

u gebruikt het sleutelwoord breidt uit om de klasse te identificeren die uw subklasse uitbreidt. Als je geen superclass declareert, breidt je Klasse Het class Object impliciet uit. Object is de wortel van alle erfelijke hiërarchieën; het is de enige klasse in Java die geen andere klasse uit te breiden.

het volgende diagram en codefragmenten tonen een voorbeeld van een eenvoudige overerving hiërarchie.,

De class BasicCoffeeMachine declareert geen superclass en breidt het class-Object impliciet uit. Je kunt het coffeemachine voorbeeld project op GitHub klonen.

De Klasse PremiumCoffeeMachine is een subklasse van de klasse BasicCoffeeMachine.

Inheritance and access modifiers

Access modifiers bepalen welke klassen toegang hebben tot een attribuut of methode. In een van mijn vorige berichten over encapsulation, liet ik je zien hoe je ze kon gebruiken om een informatie-verbergen mechanisme te implementeren. Maar dat is niet het enige geval waarin je bekend moet zijn met de verschillende modifiers., Ze hebben ook invloed op de entiteiten en attributen die u kunt openen binnen een overerving hiërarchie.

Hier is een snel overzicht van de verschillende modifiers:

  • Private attributen of methoden kunnen alleen binnen dezelfde klasse worden benaderd.
  • attributen en methoden zonder een access modifier kunnen worden benaderd binnen dezelfde klasse, en door alle andere klassen binnen hetzelfde pakket.
  • beschermde attributen of methoden kunnen worden benaderd binnen dezelfde klasse, door alle klassen binnen hetzelfde pakket en door alle subklassen.,
  • publieke attributen en methoden zijn toegankelijk voor alle klassen.

zoals u in die lijst kunt zien, heeft een subklasse toegang tot alle beschermde en publieke attributen en methoden van de superklasse. Als de subklasse en superklasse tot hetzelfde pakket behoren, kan de subklasse ook toegang krijgen tot alle package-private attributen en methoden van de superklasse.

Ik doe dat twee keer in de constructor van de premium Koffiemachine klasse.

Ik gebruik eerst het sleutelwoord super om de constructor van de superklasse aan te roepen. De constructor is openbaar en de subklasse kan er toegang toe hebben., Het trefwoord super verwijst naar de superklasse. Je kunt het gebruiken om toegang te krijgen tot een attribuut, of om een methode van de superklasse aan te roepen die wordt overschreven door de huidige subklasse. Maar daarover meer in de volgende sectie.

het beschermde attribuut configMap wordt gedefinieerd door de basiccoffeemachine klasse. Door die klasse uit te breiden, wordt het attribuut ook onderdeel van de PremiumCoffeeMachine klasse, en kan ik de configuratie toevoegen die nodig is om een espresso te brouwen aan de kaart.,

methode overschrijven

overerving voegt niet alleen alle publieke en beschermde methoden van de superklasse toe aan uw subklasse, maar het staat u ook toe om hun implementatie te vervangen. De methode van de subklasse overschrijft dan die van de superklasse. Dat mechanisme heet polymorfisme.

Ik gebruik dat in de premium Koffiemachine om de koffiezetmogelijkheden van de koffiemachine uit te breiden. De brewCoffee-methode van de basiccoffeemachine-methode kan alleen filterkoffie brouwen.

i overschrijf die methode in de klasse PremiumCoffeeMachine om ondersteuning voor de Coffeeselectie toe te voegen.,ESPRESSO. Zoals je kunt zien in het codefragment, is het super keyword erg handig als je een methode overschrijft. De brewCoffee-methode van de Basiccoffee-machine is al geschikt voor de selectie van koffie.FILTER_COFFEE en gooit een CoffeeException voor niet-ondersteunde CoffeeSelections.

dat kan ik hergebruiken in mijn nieuwe brewcoffee methode. In plaats van dezelfde logica opnieuw in te voeren, controleer ik gewoon of de Koffieselectie espresso is. Als dat niet het geval is, gebruik ik het super keyword om de brewCoffee methode van de superklasse te noemen.,

voorkomen dat een methode wordt overschreven

Als u ervoor wilt zorgen dat geen subklasse de implementatie van een methode kan veranderen, kunt u deze definitief verklaren. In het voorbeeld van deze post, ik deed dat Voor de addBeans methode van de basiccoffeemachine klasse.

Het is vaak een goed idee om alle methoden definitief te maken die door een constructor worden aangeroepen. Het voorkomt dat een subklasse, vaak onbedoeld, het gedrag van de constructeur verandert.,

een subklasse is ook van het type van zijn superklasse

een subklasse erft niet alleen de attributen en methoden van de superklasse, maar erft ook de typen van de superklasse. In het voorbeeld is de BasicCoffeeMachine van het type BasicCoffeeMachine en Object. En een PremiumCoffeeMachine object is van de types PremiumCoffeeMachine, BasicCoffeeMachine en Object.

hierdoor kunt u een PremiumCoffeeMachine-object casten om BasicCoffeeMachine te typen.

BasicCoffeeMachinee coffeeMachine = (BasicCoffeeMachine) PremiumCoffeeMachine(beans);

waarmee u code kunt schrijven die de superklasse gebruikt en uitvoeren met alle subklassen.,

in dit voorbeeld geeft de code van de createCoffeeMachine methode terug en gebruikt de makeCoffee methode de basiccoffeemachine klasse. Maar de createCoffeeMachine methode instantiates een nieuw PremiumCoffeeMachine object. Wanneer het wordt teruggegeven door de methode, wordt het object automatisch gegoten naar BasicCoffeeMachine en de code kan alle openbare methoden van de BasicCoffeeMachine klasse aanroepen.

het object coffeeMachine wordt gegoten naar BasicCoffeeMachine, maar het is nog steeds een PremiumCoffeeMachine., Dus als de makeCoffee-methode de brewcoffee-methode noemt, roept het de overgeschreven methode op op de PremiumCoffeeMachine-klasse.

definiëren van abstracte klassen

abstracte klassen zijn anders dan de andere klassen waarover we hebben gesproken. Ze kunnen worden verlengd, maar niet worden bevestigd. Dat maakt ze ideaal voor conceptuele generalisaties die niet bestaan in uw specifieke domein, maar u in staat stellen om delen van uw code te hergebruiken.

u gebruikt het trefwoord abstract om een klasse of methode abstract te verklaren. Een abstracte klasse hoeft geen abstracte methoden te bevatten., Maar een abstracte methode moet door een abstracte klasse worden verklaard.

laten we het voorbeeld van de koffiemachine herzien en de abstractcoffeemachine klasse introduceren als de superklasse van de basiccoffeemachine klasse. Ik verklaar deze klasse als abstract en definieer de abstracte 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; }

zoals u kunt zien, geef ik niet de inhoud van de abstracte brewcoffee methode. Ik verklaar het gewoon zoals ik zou doen in een interface., Wanneer u de klasse AbstractCoffeeMachine uitbreidt, moet u de subklasse als abstract definiëren, of de brewCoffee methode overschrijven om de body van de methode te implementeren.

Ik breng enkele kleine wijzigingen aan in de basiccoffeemachine klasse. Het breidt nu de AbstractCoffeeMachine-klasse uit en de reeds bestaande brewCoffee-methode overschrijft de abstracte methode van de superklasse.

een ander ding dat ik heb veranderd is de constructor van de basiccoffeemachine klasse. Het roept nu de constructor van de superclass aan en voegt een sleutel-waarde paar toe aan het configMap attribuut zonder de kaart te instantiëren., Het wordt gedefinieerd en bevestigd door de abstracte superklasse en kan in alle subklassen worden gebruikt.

Dit is een van de belangrijkste verschillen tussen een abstracte superklasse en een interface. De abstract class laat je niet alleen toe om methoden te declareren, maar je kunt ook attributen definiëren die niet statisch en definitief zijn.

samenvatting

zoals u hebt gezien, is overerving een krachtig concept dat u in staat stelt om een subklasse te implementeren die een superklasse uitbreidt. Door dat te doen, erft de subklasse alle beschermde en publieke attributen en methoden, en de types van de superklasse., U kunt vervolgens de overgeërfde attributen van de superklasse gebruiken, de overgeërfde methoden gebruiken of overschrijven en de subklasse naar elk type van de superklasse casten.

u kunt een abstracte klasse gebruiken om een algemene abstractie te definiëren die niet kan worden geïnstantieerd. Binnen die klasse kun je abstracte methoden verklaren die moeten worden overschreven door niet-abstracte subklassen. Dat wordt vaak gebruikt als de implementatie van die methode specifiek is voor elke subklasse, maar je wilt een algemene API definiëren voor alle klassen van de hiërarchie.