Het gebruik van de sleutelwoord finale met overerving in Java

Terwijl een van Java's sterke punten is het concept van overerving, waarin men klasse kan afkomstig zijn van een andere, soms is het wenselijk om overerving door een andere klasse te voorkomen. Gebruik het trefwoord "final" om overerving te voorkomen bij het maken van de klasse.

Als een klasse bijvoorbeeld waarschijnlijk door andere programmeurs wordt gebruikt, wilt u mogelijk overerving voorkomen als eventuele subklassen problemen kunnen veroorzaken. Een typisch voorbeeld is de String klasse. Als we een String-subklasse wilden maken:

public class MyString verlengt String {
}

We zouden met deze fout worden geconfronteerd:

 kan niet erven van final java.lang. Draad 

De ontwerpers van de String-klasse realiseerden zich dat het geen kandidaat was voor overerving en hebben voorkomen dat het werd uitgebreid.

Waarom overerving voorkomen?

De belangrijkste reden om te voorkomen erfenis is ervoor te zorgen dat de manier waarop een klasse zich gedraagt ​​niet wordt beschadigd door een subklasse.

Stel dat we een klasse-account hebben en een subklasse die deze uitbreidt, OverdraftAccount. Class Account heeft een methode getBalance ():

instagram viewer

 openbare dubbele getBalance ()

{

 retourneer dit. saldo;

 } 

Op dit punt in onze discussie heeft subklasse OverdraftAccount deze methode niet overschreven.

(Notitie: Zie voor een andere discussie met deze Account- en OverdraftAccount-klassen hoe een subklasse kan worden behandeld als een superklasse).

Laten we een instantie maken van elk van de klassen Account en OverdraftAccount:

 Account bobsAccount = nieuw account (10);

 bobsAccount.depositMoney (50);

 OverdraftAccount jimsAccount = nieuwe OverdraftAccount (15.05.500,0.05);

 jimsAccount.depositMoney (50);

 // maak een array van accountobjecten

 // we kunnen jimsAccount opnemen omdat we 

 // wil het alleen behandelen als een accountobject

 Account [] accounts = {bobsAccount, jimsAccount};


 // geef voor elke rekening in de array het saldo weer

 voor (Account a: accounts)

 {

 System.out.printf ("Het saldo is% .2f% n", a.getBalance ());

 }

 De output is:

 Het saldo is 60,00

 Het saldo is 65,05 

Alles lijkt hier te werken zoals verwacht. Maar wat als OverdraftAccount de methode getBalance () overschrijft? Niets kan voorkomen dat het zoiets doet:

 public class OverdraftAccount verlengt account {


 privé dubbele debetstandLimit;

 privé dubbele debetstand;


 // de rest van de klassendefinitie is niet inbegrepen


 openbare dubbele getBalance ()

 {

 retour 25.00;

 }

 } 

Als de bovenstaande voorbeeldcode opnieuw wordt uitgevoerd, zal de uitvoer anders zijn omdat het gedrag van vegetBalance () in de klasse OverdraftAccount wordt aangeroepen voor jimsAccount:

 De output is:

 Het saldo is 60,00

 Het saldo is 25,00 

Helaas zal de subklasse OverdraftAccount dat wel doen nooit zorgen voor het juiste saldo omdat we het gedrag van de klasse Account hebben beschadigd door overerving.

Als u een klasse ontwerpt die door andere programmeurs kan worden gebruikt, moet u altijd rekening houden met de implicaties van mogelijke subklassen. Dit is de reden dat de String-klasse niet kan worden uitgebreid. Het is uiterst belangrijk dat programmeurs weten dat wanneer ze een String-object maken, het zich altijd als een String gaat gedragen.

Hoe erfelijkheid te voorkomen

Om te voorkomen dat een klasse wordt uitgebreid, moet de klasseverklaring expliciet aangeven dat deze niet kan worden geërfd. Dit wordt bereikt door het "laatste" trefwoord te gebruiken:

 openbare finale klasaccount {


 } 

Dit betekent dat de klasse Account geen superklasse kan zijn en de klasse OverdraftAccount niet langer de subklasse kan zijn.

Soms wilt u misschien alleen bepaald gedrag van een superklasse beperken om corruptie door een subklasse te voorkomen. OverdraftAccount kan bijvoorbeeld nog steeds een subklasse van Account zijn, maar er moet worden voorkomen dat de methode getBalance () wordt overschreven.

Gebruik in dit geval het "laatste" trefwoord in de methodeaangifte:

 account voor openbare klasse {


 privé dubbel saldo;


 // de rest van de klassendefinitie is niet inbegrepen


 openbare finale dubbele getBalance ()

 {

 retourneer dit. saldo;

 } 

 } 

Merk op hoe het uiteindelijke sleutelwoord niet wordt gebruikt in de klassendefinitie. Er kunnen subklassen van Account worden gemaakt, maar ze kunnen de methode getBalance () niet langer negeren. Elke code die die methode aanroept, kan erop vertrouwen dat deze zal werken zoals de oorspronkelijke programmeur het bedoeld heeft.

instagram story viewer