Zatímco jeden z Java silnými stránkami je pojem dědičnosti, ve kterém jeden třída může pocházet z jiné, někdy je žádoucí zabránit dědičnosti jinou třídou. Chcete-li zabránit dědičnosti, použijte při vytváření třídy klíčové slovo „final“.
Pokud například třídu pravděpodobně použijí jiní programátoři, můžete zabránit dědičnosti, pokud by vytvořené podtřídy mohly způsobit problémy. Typickým příkladem je Třída strun. Pokud bychom chtěli vytvořit podtřídu String:
public class MyString rozšiřuje String {
}
Byli bychom čelili této chybě:
nemůže zdědit finální java.lang. Tětiva
Designéři třídy String si uvědomili, že to není kandidát na dědictví, a zabránili jeho rozšíření.
Proč zabránit dědičnosti?
Hlavním důvodem, proč tomu zabránit dědictví je zajistit, aby způsob chování třídy nebyl poškozen podtřídou.
Předpokládejme, že máme účet třídy a podtřídu, která jej rozšiřuje, OverdraftAccount. Účet třídy má metodu getBalance ():
veřejná dvojitá getBalance ()
{
vrátit this.balance;
}
V této chvíli v naší diskusi podtřída OverdraftAccount tuto metodu nepřepsala.
(Poznámka: Pro další diskusi používající tento účet a třídy přečerpání účtu, viz podtřída může být považována za nadřazenou).
Vytvořme instanci každé z tříd Account a OverdraftAccount:
BobsAccount = nový účet (10);
bobsAccount.depositMoney (50);
OverdraftAccount jimsAccount = nový OverdraftAccount (15.05,500,0.05);
jimsAccount.depositMoney (50);
// vytvořit pole objektů Account
// můžeme zahrnout jimsAccount, protože my
// chtějí to považovat pouze za objekt účtu
Účet [] accounts = {bobsAccount, jimsAccount};
// u každého účtu v poli zobrazte zůstatek
pro (Účet a: účty)
{
System.out.printf ("Zůstatek je% .2f% n", a.getBalance ());
}
Výstup je:
Zůstatek je 60,00
Zůstatek je 65,05
Zdá se, že všechno funguje podle očekávání. Co když však OverdraftAccount přepíše metodu getBalance ()? Nic nebrání tomu, aby něco takového udělal:
veřejná třída OverdraftAccount rozšiřuje účet {
soukromé dvojnásobné přečerpáníLimit;
soukromé dvojnásobné přečerpání;
// zbytek definice třídy není zahrnut
veřejná dvojitá getBalance ()
{
návrat 25,00;
}
}
Pokud je výše uvedený příkladový kód spuštěn znovu, bude výstup jiný, protože chování jimgetBalance () ve třídě OverdraftAccount se volá jimsAccount:
Výstup je:
Zůstatek je 60,00
Zůstatek je 25,00
Bohužel podtřída OverdraftAccount bude nikdy poskytnout správný zůstatek, protože jsme porušili chování třídy Account zděděním.
Pokud navrhujete třídu, kterou budou používat jiní programátoři, vždy zvažte případné podtřídy. Z tohoto důvodu nelze třídu String rozšířit. Je nesmírně důležité, aby programátoři věděli, že když vytvoří objekt String, bude se vždy chovat jako String.
Jak zabránit dědičnosti
Aby nedošlo k rozšíření třídy, musí deklarace třídy výslovně říci, že ji nelze zdědit. Toho je dosaženo pomocí klíčového slova „final“:
účet veřejné závěrečné třídy {
}
To znamená, že třída Account nemůže být nadřazenou třídou a třída OverdraftAccount již nemůže být její podtřídou.
Někdy můžete chtít omezit pouze určitá chování nadřazené třídy, aby nedošlo k poškození podtřídy. Například OverdraftAccount by stále mohl být podtřídou Account, ale mělo by se zabránit tomu, aby potlačil metodu getBalance ().
V tomto případě použijte klíčové slovo „konečné“ v deklaraci metody:
účet veřejné třídy {
soukromá dvojitá rovnováha;
// zbytek definice třídy není zahrnut
veřejný finální double getBalance ()
{
vrátit this.balance;
}
}
Všimněte si, jak se v definici třídy nepoužívá konečné klíčové slovo. Lze vytvořit podtřídy účtu, ale již nemohou přepsat metodu getBalance (). Jakýkoli kód, který volá tuto metodu, si může být jistý, že bude fungovat podle původního zamýšleného programátora.