OOP koncept for begyndere: Hvad er arv?
arv er et af de centrale begreber i objektorienteret programmering (OOP) sprog. Det er en mekanisme, hvor du kan udlede en klasse fra en anden klasse for et hierarki af klasser, der deler et sæt attributter og metoder.
Du kan bruge den til at erklære forskellige slags undtagelser, tilføje brugerdefineret logik til eksisterende rammer og endda kortlægge din domænemodel til en database.,
erklære et arvshierarki
i Java kan hver klasse kun afledes fra en anden klasse. Denne klasse kaldes en superklasse eller forældreklasse. Den afledte klasse kaldes underklasse eller børneklasse.
du bruger nøgleordet udvider for at identificere den klasse, som din underklasse udvider. Hvis du ikke erklærer en superklasse, udvider din klasse implicit klasseobjektet. Objekt er roden til alle arv hierarkier; det er den eneste klasse i Java, der ikke udvider en anden klasse.
følgende diagram og kodestykker viser et eksempel på et simpelt arvehierarki.,
klassen BasicCoffeeMachine erklærer ikke en superklasse og udvider implicit klasseobjektet. Du kan klone CoffeeMachine eksempel projekt på GitHub.
klassen PremiumCoffeeMachine er en underklasse af BasicCoffeeMachine klassen.
arv og adgang modifikatorer
adgang modifikatorer definere, hvad klasser kan få adgang til en attribut eller metode. I et af mine tidligere indlæg om indkapsling viste jeg dig, hvordan du kunne bruge dem til at implementere en informations-skjulingsmekanisme. Men det er ikke det eneste tilfælde, hvor du skal være bekendt med de forskellige modifikatorer., De påvirker også de enheder og attributter, som du kan få adgang til inden for en arv hierarki.
Her er et hurtigt overblik over de forskellige modifikatorer:
- Private attributter eller metoder kan kun tilgås inden for samme klasse.
- attributter og metoder uden en adgangsmodifikator kan tilgås inden for samme klasse, og af alle andre klasser inden for samme pakke.
- beskyttede attributter eller metoder kan tilgås inden for samme klasse, af alle klasser inden for samme pakke, og af alle underklasser.,offentlige attributter og metoder kan tilgås af alle klasser.
som du kan se på denne liste, kan en underklasse få adgang til alle beskyttede og offentlige attributter og metoder til superklassen. Hvis underklassen og superklassen hører til den samme pakke, kan underklassen også få adgang til alle pakke-private attributter og metoder til superklassen.
Jeg gør det to gange i konstruktøren af PremiumCoffeeMachine-klassen.
Jeg bruger først søgeordet super til at kalde konstruktøren af superklassen. Konstruktøren er offentlig, og underklassen kan få adgang til den., Nøgleordet super refererer superklassen. Du kan bruge den til at få adgang til en attribut eller til at kalde en metode til superklassen, der tilsidesættes af den nuværende underklasse. Men mere om det i det følgende afsnit.
den beskyttede attribut configMap bliver defineret af BasicCoffeeMachine klassen. Ved at udvide denne klasse bliver attributten også en del af PremiumCoffeeMachine-klassen, og jeg kan tilføje den konfiguration, der kræves for at brygge en espresso til kortet.,
metode overstyring
arv tilføjer ikke kun alle offentlige og beskyttede metoder til superklassen til din underklasse, men det giver dig også mulighed for at erstatte deres implementering. Metoden til underklassen tilsidesætter derefter superklassen. Denne mekanisme kaldes polymorfisme.
Jeg bruger det i PremiumCoffeeMachine-klassen for at udvide kaffemaskinens kaffebryggeevne. Breffcoffee-metoden for den Grundlæggendecoffeemachine-metoden kan kun brygge filterkaffe.
Jeg tilsidesætter denne metode i PremiumCoffeeMachine-klassen for at tilføje support til CoffeeSelection.,ESPRESSO. Som du kan se i kodestykket, er super-nøgleordet meget nyttigt, hvis du tilsidesætter en metode. Breffcoffee-metoden for den Grundlæggendekaffemaskine håndterer allerede Kaffevalget.FILTER_COFFEE og kaster en Coffeecception for ikke-understøttede CoffeeSelections.
Jeg kan genbruge det i min nye Bre .coffee metode. I stedet for at genimplementere den samme logik, kontrollerer jeg bare, om Kaffevalget er ESPRESSO. Hvis det ikke er tilfældet, bruger jeg super nøgleordet til at kalde breffcoffee-metoden for superklassen.,
forhindre, at en metode tilsidesættes
Hvis du vil sikre dig, at ingen underklasse kan ændre implementeringen af en metode, kan du erklære den for endelig. I dette indlægs eksempel gjorde jeg det for addBeans-metoden i BasicCoffeeMachine-klassen.
det er ofte en god ide at gøre alle metoder endelige, der kaldes af en konstruktør. Det forhindrer enhver underklasse fra, ofte utilsigtet, at ændre konstruktørens opførsel.,
en underklasse er også af typen af dens superklasse
en underklasse arver ikke kun attributterne og metoderne til superklassen, men den arver også typerne af superklassen. I eksemplet er den BasicCoffeeMachine af typen BasicCoffeeMachine and Object. Og en PremiumCoffeeMachine objekt er af typerne PremiumCoffeeMachine, BasicCoffeeMachine, og objekt.på grund af dette kan du kaste et PremiumCoffeeMachine-objekt for at skrive BasicCoffeeMachine.
BasicCoffeeMachinee coffeeMachine = (BasicCoffeeMachine) PremiumCoffeeMachine(beans);
det giver dig mulighed for at skrive kode, der bruger superklassen og udføre den med alle underklasser.,
i dette eksempel vender koden til createCoffeeMachine-metoden tilbage, og makeCoffee-metoden bruger basiccoffeemachine-klassen. Men createCoffeeMachine-metoden instantierer en ny PremiumCoffeeMachine-objekt. Når det bliver returneret af metoden, objektet er automatisk støbt til BasicCoffeeMachine og koden kan kalde alle offentlige metoder i basiccoffeemachine klasse.coffeeMachine-objektet bliver kastet til BasicCoffeeMachine, men det er stadig en PremiumCoffeeMachine., Så når makeCoffee-metoden kalder Bre .coffee-metoden, kalder den den tilsidesættede metode på PremiumCoffeeMachine-klassen.
definition af abstrakte klasser
abstrakte klasser er forskellige end de andre klasser, vi har talt om. De kan forlænges, men ikke instantieres. Det gør dem ideelle til at repræsentere konceptuelle generaliseringer, der ikke findes i dit specifikke domæne, men giver dig mulighed for at genbruge dele af din kode.
du bruger nøgleordet abstrakt til at erklære en klasse eller metode til at være abstrakt. En abstrakt klasse behøver ikke at indeholde abstrakte metoder., Men en abstrakt metode skal erklæres af en abstrakt klasse.
lad os refactor kaffemaskinen eksempel og introducere abstractcoffeemachine klasse som superklassen af BasicCoffeeMachine klasse. Jeg erklærer, at klassen som abstrakt og definere den abstrakte Bre .coffee metode.
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, giver jeg ikke kroppen af den abstrakte Bre .coffee-metode. Jeg erklærer det bare som jeg ville gøre i en grænseflade., Når du udvider abstractcoffeemachine-klassen, skal du definere underklassen som abstrakt eller tilsidesætte Bre .coffee-metoden for at implementere metodekroppen.
jeg foretager nogle mindre ændringer i basiccoffeemachine-klassen. Det udvider nu abstractcoffeemachine-klassen, og den allerede eksisterende Bre .coffee-metode tilsidesætter superklassens abstrakte metode.
en anden ting, jeg ændrede, er konstruktøren af BasicCoffeeMachine-klassen. Det kalder nu konstruktøren af superklassen og tilføjer et nøgleværdipar til configMap-attributten uden at instantiere kortet., Den er defineret og instantieret af den abstrakte superklasse og kan bruges i alle underklasser.
Dette er en af de vigtigste forskelle mellem en abstrakt superklasse og en grænseflade. Den abstrakte klasse giver dig ikke kun mulighed for at erklære metoder, men du kan også definere attributter, der ikke er statiske og endelige.
resum As
som du har set, er arv et kraftfuldt koncept, der giver dig mulighed for at implementere en underklasse, der udvider en superklasse. Ved at gøre det, arver underklassen alle beskyttede og offentlige attributter og metoder, og typerne af superklassen., Du kan derefter bruge superklassens nedarvede attributter, bruge eller tilsidesætte de nedarvede metoder og kaste underklassen til enhver type superklasse.
Du kan bruge en abstrakt klasse til at definere en generel abstraktion, der ikke kan instantieres. Inden for denne klasse kan du erklære abstrakte metoder, der skal tilsidesættes af ikke-abstrakte underklasser. Det bruges ofte, hvis implementeringen af denne metode er specifik for hver underklasse, men du vil definere en generel API for alle klasser i hierarkiet.