Mens en af Javas styrker er begrebet arv, hvori en klasse kan stamme fra en anden, sommetider er det ønskeligt at forhindre arv fra en anden klasse. For at forhindre arv skal du bruge nøgleordet "final", når du opretter klassen.
For eksempel, hvis en klasse sandsynligvis vil blive brugt af andre programmerere, kan du eventuelt forhindre arv, hvis oprettede underklasser kan forårsage problemer. Et typisk eksempel er Streng klasse. Hvis vi ville oprette en strengunderklasse:
offentlig klasse MyString udvider streng {
}
Vi vil blive konfronteret med denne fejl:
kan ikke arve fra endelig java.lang. Snor
Designerne af String-klassen indså, at det ikke var en kandidat til arv og har forhindret den i at blive udvidet.
Hvorfor forhindre arv?
Den vigtigste grund til at forhindre arv er at sikre, at en klasses opførsel ikke beskadiges af en underklasse.
Antag, at vi har en klasse-konto og en underklasse, der udvider den, OverdraftAccount. Klassekonto har en metode getBalance ():
offentlig dobbelt getBalance ()
{
returner denne. balance;
}
På dette tidspunkt i vores diskussion har underklasse OverdraftAccount ikke tilsidesat denne metode.
(Bemærk: For en anden diskussion ved hjælp af klassen Konto og Overtrækningskonti, se hvordan a underklasse kan behandles som en superklasse).
Lad os oprette en forekomst hver af klasserne Konto og Overtrækningskonti:
KontobobsAccount = ny konto (10);
bobsAccount.depositMoney (50);
OverdraftAccount jimsAccount = nyt OverdraftAccount (15.05.500.0.05);
jimsAccount.depositMoney (50);
// oprette en række kontoobjekter
// vi kan inkludere jimsAccount fordi vi
// vil kun behandle det som et kontoobjekt
Konto [] konti = {bobsAccount, jimsAccount};
// Vis saldoen for hver konto i matrixen
for (Konto a: konti)
{
System.out.printf ("Balancen er% .2f% n", a.getBalance ());
}
Outputet er:
Restbeløbet er 60,00
Restbeløbet er 65,05
Alt ser ud til at fungere som forventet her. Men hvad nu hvis OverdraftAccount tilsidesætter metoden getBalance ()? Der er ikke noget, der forhindrer det i at gøre sådan noget:
offentlig klasse-kassekredit udvider konto {
privat dobbelt overtræk Limit;
privat dobbelt kassekreditgebyr;
// resten af klassedefinitionen er ikke inkluderet
offentlig dobbelt getBalance ()
{
retur 25,00;
}
}
Hvis eksemplekoden ovenfor udføres igen, vil output være anderledes, fordi opførelsen thegetBalance () i klassen OverdraftAccount kaldes til jimsAccount:
Outputet er:
Restbeløbet er 60,00
Restbeløbet er 25,00
Desværre er underklassen Overdækningskonto aldrig give den korrekte balance, fordi vi har ødelagt opførelsen af Kontoklassen gennem arv.
Hvis du designer en klasse, der skal bruges af andre programmerere, skal du altid overveje konsekvenserne af eventuelle underklasser. Dette er grunden til, at strengeklassen ikke kan udvides. Det er ekstremt vigtigt, at programmerere ved, at når de opretter et strengobjekt, det altid vil opføre sig som en streng.
Sådan forhindres arv
For at forhindre, at en klasse udvides, skal klassedeklarationen udtrykkeligt sige, at den ikke kan arves. Dette opnås ved at bruge det "endelige" nøgleord:
offentlig slutklassekonto {
}
Dette betyder, at Kontoklassen ikke kan være en superklasse, og OverdraftAccount-klassen kan ikke længere være dens underklasse.
Nogle gange kan du måske kun ønske at begrænse visse opførsler fra en superklasse for at undgå korruption af en underklasse. F.eks. Kan OverdraftAccount stadig være en underklasse i Konto, men det bør forhindres i at tilsidesætte metoden getBalance ().
I dette tilfælde brug af det "endelige" nøgleord i metodedeklarationen:
offentlig klasse konto {
privat dobbelt balance;
// resten af klassedefinitionen er ikke inkluderet
offentlig endelig dobbelt getBalance ()
{
returner denne. balance;
}
}
Bemærk, hvordan det endelige nøgleord ikke bruges i klassedefinitionen. Underklasser af konti kan oprettes, men de kan ikke længere tilsidesætte metoden getBalance (). Enhver kode, der kalder denne metode, kan være sikker på, at den fungerer som den oprindelige programmerer havde til hensigt.