Arv (Svenska)
I föregående lektioner har du sett arv nämnts flera gånger. På Java-språket kan klasser härledas från andra klasser och därigenom ärva fält och metoder från dessa klasser.
Med undantag för
Object
, som inte har någon superklass, har varje klass en och bara en direkt superklass (enda arv). I avsaknad av någon annan uttrycklig superklass är varje klass implicit en underklass av Object
. Klasser kan härledas från klasser som härrör från klasser som härrör från klasser, och så vidare, och slutligen härledd från den översta klassen,
Object
. En sådan klass sägs härstamma från alla klasser i arvskedjan som sträcker sig tillbaka till Object
. Idén med arv är enkel men kraftfull: När du vill skapa en ny klass och det redan finns en klass som innehåller en del av koden du vill, kan du härleda din nya klass från den befintliga klassen . Genom att göra detta kan du återanvända fälten och metoderna för den befintliga klassen utan att behöva skriva (och felsöka!) Dem själv.
En underklass ärver alla medlemmar (fält, metoder och kapslade klasser) från dess superklass. Konstruktörer är inte medlemmar, så de ärvs inte av underklasser, men superklassens konstruktör kan åberopas från underklassen.
Java Platform Class Hierarchy
Object
-klassen, definierad i java.lang
-paketet, definierar och implementerar beteenden som är gemensamma för alla klasser – inklusive de som du skriver. På Java-plattformen härrör många klasser direkt från Object
, andra klasser härrör från några av dessa klasser och så vidare och bildar en hierarki av klasser.
Alla klasser i Java-plattformen är ättlingar till objekt
Högst upp i hierarkin är Object
den mest generella av alla klasser. Klasser nära botten av hierarkin ger mer specialiserat beteende.
Ett exempel på arv
Här är exempelkoden för en möjlig implementering av en Bicycle
class som presenterades i lektionen Classes and Objects:
En klassdeklaration för en MountainBike
-klass som är en underklass av Bicycle
kan se ut så här:
public class MountainBike extends Bicycle { // the MountainBike subclass adds one field public int seatHeight; // the MountainBike subclass has one constructor public MountainBike(int startHeight, int startCadence, int startSpeed, int startGear) { super(startCadence, startSpeed, startGear); seatHeight = startHeight; } // the MountainBike subclass adds one method public void setHeight(int newValue) { seatHeight = newValue; } }
MountainBike
ärver alla fält och metoder för Bicycle
och lägger till fältet seatHeight
och en metod för att ställa in det. Med undantag för konstruktören är det som om du hade skrivit en ny MountainBike
-klass helt från grunden, med fyra fält och fem metoder. Du behövde dock inte göra allt arbete. Detta skulle vara särskilt värdefullt om metoderna i klassen Bicycle
var komplexa och hade tagit lång tid att felsöka.
Vad du kan göra i en underklass
En underklass ärver alla offentliga och skyddade medlemmar av sin förälder, oavsett vilket paket underklassen är i. Om underklassen finns i samma paket som dess förälder, det ärver också de förälders paketprivata medlemmar. Du kan använda de ärvda medlemmarna som de är, ersätta dem, dölja dem eller komplettera dem med nya medlemmar:
- De ärvda fälten kan kan användas direkt, precis som alla andra fält.
- Du kan förklara ett fält i underklassen med samma namn som det i superklassen och därmed dölja det (rekommenderas inte).
- Du kan deklarera nya fält i underklassen som inte finns i superklassen.
- De ärvda metoderna kan användas direkt som de är.
- Du kan skriva en ny instansmetod i underklass det har samma signatur som den i superklassen, vilket åsidosätter den.
- Du kan skriva en ny statisk metod i underklassen som har samma signatur som den i superklassen och därmed dölja den.
- Du kan deklarera nya metoder i underklassen som inte finns i superklassen.
- Du kan skriva en underklasskonstruktör som anropar superklassens konstruktör, antingen implicit eller med hjälp av nyckelordet
super
.
Följande avsnitt i den här lektionen utvidgas om dessa ämnen.
Privata medlemmar i en superklass
En underklass ärver inte private
medlemmarna i sin överordnade klass. Men om superklassen har offentliga eller skyddade metoder för att komma åt sina privata fält, kan dessa också användas av underklassen.
En kapslad klass har tillgång till alla privata medlemmar i sin slutande klass – både fält och metoder. Därför har en offentlig eller skyddad kapslad klass som ärvs av en underklass indirekt tillgång till alla privata medlemmar i superklassen.
Casting Objects
Vi har sett att ett objekt är av datatyp för den klass från vilken den instanserades. Om vi till exempel skriver
public MountainBike myBike = new MountainBike();
så är myBike
av typen MountainBike
.
MountainBike
härstammar från Bicycle
och Object
. Därför är en MountainBike
en Bicycle
och är också en Object
, och det kan vara används var som helst Bicycle
eller Object
objekt efterfrågas.
Det omvända är inte nödvändigtvis sant: a Bicycle
kan vara en MountainBike
, men det är inte nödvändigtvis. På samma sätt kan en Object
vara Bicycle
eller en MountainBike
, men det är inte nödvändigtvis.
Casting visar användningen av ett objekt av en skriv i stället för en annan typ, bland de föremål som är tillåtna genom arv och implementeringar. Om vi till exempel skriver
Object obj = new MountainBike();
är obj
båda en Object
och en MountainBike
(tills obj
tilldelas ett annat objekt som inte är MountainBike
). Detta kallas implicit casting.
Om vi däremot skriver
MountainBike myBike = obj;
skulle vi få ett kompileringsfel eftersom obj
inte är känt av kompilatorn för att vara en MountainBike
. Vi kan dock berätta för kompilatorn att vi lovar att tilldela en MountainBike
till obj
genom uttrycklig casting:
MountainBike myBike = (MountainBike)obj;
Denna gjutning infogar en runtime-kontroll att obj
tilldelas en MountainBike
så att kompilatorn säkert kan anta att obj
är en MountainBike
. Om obj
inte är MountainBike
vid körning kommer ett undantag att kastas.
instanceof
. Detta kan spara dig från ett runtime-fel på grund av en felaktig roll. Till exempel:
if (obj instanceof MountainBike) { MountainBike myBike = (MountainBike)obj;}
Här verifierar instanceof
operatören att obj
hänvisar till en MountainBike
så att vi kan göra rollbesättningen med vetskap om att det inte kommer att finnas något undantag för runtime.