Articles

OOP koncept för nybörjare: Vad är arv?

Arv är en av de grundläggande begreppen objektorienterad programmering (OOP) språk. Det är en mekanism där du kan härleda en klass från en annan klass för en hierarki av klasser som delar en uppsättning attribut och metoder.

Du kan använda den för att deklarera olika typer av undantag, lägga till anpassad logik i befintliga ramar och till och med mappa din domänmodell till en databas.,

deklarera en arvshierarki

i Java kan varje klass endast härledas från en annan klass. Den klassen kallas en superklass eller föräldraklass. Den härledda klassen kallas underklass eller barnklass.

du använder sökordet utökar för att identifiera klassen som din underklass utökar. Om du inte deklarerar en superklass utökar klassen implicit klassobjektet. Objektet är roten till alla arv hierarkier; det är den enda klassen i Java som inte utökar en annan klass.

Följande diagram och kodavsnitt visar ett exempel på en enkel arvshierarki.,

klassen BasicCoffeeMachine deklarerar inte en superklass och förlänger implicit klassobjektet. Du kan klona Exempelprojektet CoffeeMachine på GitHub.

klassen PremiumCoffeeMachine är en underklass i klassen BasicCoffeeMachine.

arvs-och åtkomstmodifierare

åtkomstmodifierare definierar vilka klasser som kan komma åt ett attribut eller en metod. I ett av mina tidigare inlägg om inkapsling visade jag dig hur du kunde använda dem för att implementera en informationshöjningsmekanism. Men det är inte det enda fallet där du måste vara bekant med de olika modifierarna., De påverkar också de enheter och attribut som du kan komma åt i en arvshierarki.

Här är en snabb översikt över de olika modifierare:

  • privata attribut eller metoder kan endast nås inom samma klass.
  • attribut och metoder utan åtkomstmodifierare kan nås inom samma klass och av alla andra klasser inom samma paket.
  • skyddade attribut eller metoder kan nås inom samma klass, av alla klasser inom samma paket och av alla underklasser.,
  • offentliga attribut och metoder kan nås av alla klasser.

som du kan se i den listan kan en underklass komma åt alla skyddade och offentliga attribut och metoder för superklassen. Om underklassen och superklassen tillhör samma paket kan underklassen också komma åt alla paket-privata attribut och metoder för superklassen.

Jag gör det två gånger i konstruktören av PremiumCoffeeMachine-klassen.

Jag använder först nyckelordet super för att ringa konstruktören av superklassen. Konstruktören är offentlig, och underklassen kan komma åt den., Nyckelordet Super referenser superklass. Du kan använda den för att komma åt ett attribut, eller för att ringa en metod för superklassen som blir åsidosatt av den aktuella underklassen. Men mer om det i följande avsnitt.

det skyddade attributet configMap definieras av klassen BasicCoffeeMachine. Genom att utvidga den klassen blir attributet också en del av PremiumCoffeeMachine-klassen, och jag kan lägga till den konfiguration som krävs för att brygga en espresso på kartan.,

metod åsidosättande

Arv lägger inte bara till alla offentliga och skyddade metoder för superklassen till din underklass, men det låter dig också ersätta deras genomförande. Metoden för underklassen åsidosätter sedan den av superklassen. Den mekanismen kallas polymorfism.

Jag använder det i PremiumCoffeeMachine-klassen för att utöka kaffebryggningsförmågan hos kaffemaskinen. BrewCoffee-metoden för den Grundläggandekoffeemachinmetoden kan bara brygga filterkaffe.

jag åsidosätter den metoden i PremiumCoffeeMachine-klassen för att lägga till stöd för Kaffevalet.,ESPRESSO. Som du kan se i kodavsnittet är super-sökordet till stor hjälp om du åsidosätter en metod. BrewCoffee-metoden för den Grundläggandekaffemaskin hanterar redan Kaffevalet.FILTER_COFFEE och kastar en CoffeeException för att inte stöds CoffeeSelections.

Jag kan återanvända det i min nya brewCoffee-metod. Istället för att genomföra samma logik kontrollerar jag bara om Kaffevalet är ESPRESSO. Om så inte är fallet använder jag super nyckelordet för att ringa brewcoffee-metoden för superklassen.,

förhindra att en metod åsidosätts

om du vill se till att ingen underklass kan ändra implementeringen av en metod kan du förklara att den är slutgiltig. I det här inläggets exempel gjorde jag det för addBeans-metoden för BasicCoffeeMachine-klassen.

det är ofta en bra idé att göra alla metoder slutliga som kallas av en konstruktör. Det förhindrar någon underklass från, ofta oavsiktligt, att ändra konstruktörens beteende.,

en underklass är också av typen av dess superklass

en underklass ärver inte bara superklassens attribut och metoder, utan ärver också typerna av superklassen. I exemplet är den Grundläggandekaffemaskin är av typ BasicCoffeeMachine och objekt. Och ett PremiumCoffeeMachine objekt är av typerna PremiumCoffeeMachine, BasicCoffeeMachine och objekt.

På grund av detta kan du kasta ett PremiumCoffeeMachine-objekt för att skriva BasicCoffeeMachine.

BasicCoffeeMachinee coffeeMachine = (BasicCoffeeMachine) PremiumCoffeeMachine(beans);

som gör att du kan skriva kod som använder superklassen och köra den med alla underklasser.,

i det här exemplet returnerar koden för createCoffeeMachine-metoden och makeCoffee-metoden använder klassen BasicCoffeeMachine. Men createCoffeeMachine-metoden instansierar ett nytt PremiumCoffeeMachine-objekt. När det returneras med metoden kastas objektet automatiskt till BasicCoffeeMachine och koden kan ringa alla offentliga metoder för BasicCoffeeMachine-klassen.

coffeeMachine-objektet blir gjutet till BasicCoffeeMachine, men det är fortfarande en PremiumCoffeeMachine., Så när makeCoffee-metoden kallar brewCoffee-metoden, kallas den åsidosatta metoden på PremiumCoffeeMachine-klassen.

definiera abstrakta klasser

abstrakta klasser skiljer sig från de andra klasserna som vi har pratat om. De kan förlängas, men inte instansieras. Det gör dem idealiska för att representera konceptuella generaliseringar som inte finns i din specifika domän, men gör att du kan återanvända delar av din kod.

du använder nyckelordet abstrakt för att förklara en klass eller metod för att vara abstrakt. En abstrakt klass behöver inte innehålla några abstrakta metoder., Men en abstrakt metod måste deklareras av en abstrakt klass.

låt oss refactor kaffemaskinen exempel och introducera AbstractCoffeeMachine klass som superklass av BasicCoffeeMachine klass. Jag förklarar den klassen som abstrakt och definierar den abstrakta brewCoffee-metoden.

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; }

som du kan se ger jag inte kroppen av den abstrakta brewCoffee-metoden. Jag förklarar det som jag skulle göra i ett gränssnitt., När du förlänger AbstractCoffeeMachine-klassen måste du definiera underklassen som abstrakt eller åsidosätta brewCoffee-metoden för att genomföra metodkroppen.

Jag gör några mindre ändringar i klassen BasicCoffeeMachine. Det utökar nu AbstractCoffeeMachine-klassen, och den redan befintliga brewCoffee-metoden åsidosätter superklassens abstrakta metod.

en annan sak jag ändrade är konstruktören av BasicCoffeeMachine-klassen. Det kallar nu konstruktören av superklassen och lägger till ett nyckelvärdespar till attributet configMap utan att instansiera kartan., Den definieras och instansieras av den abstrakta superklassen och kan användas i alla underklasser.

detta är en av de viktigaste skillnaderna mellan en abstrakt superklass och ett gränssnitt. Den abstrakta klassen låter dig inte bara förklara metoder, men du kan också definiera attribut som inte är statiska och slutliga.

sammanfattning

som du har sett är arv ett kraftfullt koncept som gör att du kan implementera en underklass som utökar en superklass. Genom att göra det ärver underklassen alla skyddade och offentliga attribut och metoder och typerna av superklassen., Du kan sedan använda de ärvda attributen för superklassen, använda eller åsidosätta de ärvda metoderna och kasta underklassen till vilken typ av superklass som helst.

Du kan använda en abstrakt klass för att definiera en allmän abstraktion som inte kan instansieras. Inom den klassen kan du förklara abstrakta metoder som måste åsidosättas av icke-abstrakta underklasser. Det används ofta om implementeringen av den metoden är specifik för varje underklass, men du vill definiera ett allmänt API för alla klasser i hierarkin.