Articles

koncept OOP pro začátečníky: Co je dědičnost?

dědičnost je jedním ze základních pojmů objektově orientovaných programovacích (OOP) jazyků. Je to mechanismus, kde můžete odvodit třídu z jiné třídy pro hierarchii tříd, které sdílejí sadu atributů a metod.

můžete jej použít k deklaraci různých druhů výjimek, přidání vlastní logiky do stávajících rámců a dokonce i mapování modelu domény do databáze.,

deklarujte hierarchii dědičnosti

v Javě, každá třída může být odvozena pouze z jedné jiné třídy. Tato třída se nazývá superclass, nebo mateřská třída. Odvozená třída se nazývá podtřída nebo dětská třída.

Klíčové slovo používáte k identifikaci třídy, kterou vaše podtřída rozšiřuje. Pokud nevyhlásíte supertřídu, vaše třída implicitně rozšiřuje objekt třídy. Objekt je kořenem všech hierarchií dědičnosti; je to jediná třída v Javě, která nerozšiřuje jinou třídu.

následující diagram a úryvky kódu ukazují příklad jednoduché hierarchie dědičnosti.,

třída BasicCoffeeMachine nevyhlašuje superclass a implicitně rozšiřuje objekt třídy. Můžete klonovat příklad projektu CoffeeMachine na Githubu.

třída PremiumCoffeeMachine je podtřída třídy BasicCoffeeMachine.

modifikátory dědičnosti a přístupu

modifikátory přístupu definují, jaké třídy mají přístup k atributu nebo metodě. V jednom z mých předchozích příspěvků o zapouzdření jsem vám ukázal, jak je můžete použít k implementaci mechanismu skrývání informací. Ale to není jediný případ, kdy musíte být obeznámeni s různými modifikátory., Ovlivňují také entity a atributy, ke kterým máte přístup v hierarchii dědičnosti.

zde je rychlý přehled různých modifikátorů:

  • soukromé atributy nebo metody lze přistupovat pouze ve stejné třídě.
  • atributy a metody bez modifikátoru přístupu lze přistupovat ve stejné třídě a ve všech ostatních třídách ve stejném balíčku.
  • Chráněné atributy nebo metody lze přistupovat ve stejné třídě, všemi třídami ve stejném balíčku a všemi podtřídami.,
  • veřejné atributy a metody jsou přístupné všemi třídami.

jak vidíte v tomto seznamu, podtřída má přístup ke všem chráněným a veřejným atributům a metodám superclass. Pokud podtřída a podtřída patří do stejného balíčku, podtřída může také přistupovat ke všem atributům balíčku-soukromým atributům a metodám superclass.

dělám to dvakrát v konstruktoru třídy PremiumCoffeeMachine.

nejprve používám Klíčové slovo super k volání konstruktoru superclass. Konstruktor je veřejný a podtřída k němu má přístup., Klíčové slovo super odkazuje na superclass. Můžete jej použít k přístupu k atributu nebo k volání metody superclass, která je přepsána aktuální podtřídou. Ale více o tom v následující části.

chráněný atribut configMap je definován třídou BasicCoffeeMachine. Rozšířením této třídy, atribut se také stává součástí PremiumCoffeeMachine třídy, a můžu přidat konfiguraci, že je nutné, aby vařit espresso na Mapě.,

Metoda přepsání

Dědictví nejen přidá všechny veřejné a chráněné metody nadřazené třídy, aby své podtřídy, ale to také umožňuje nahradit jejich provádění. Metoda podtřídy pak přepíše jednu z podtříd. Tento mechanismus se nazývá polymorfismus.

používám to ve třídě PremiumCoffeeMachine k rozšíření možností vaření kávy v kávovaru. Metoda brewCoffee BasicCoffeeMachine metoda může vařit pouze filtrační kávu.

tuto metodu přepisuji ve třídě PremiumCoffeeMachine a přidám podporu pro CoffeeSelection.,KÁVOVAR. Jak můžete vidět v úryvku kódu, Klíčové slovo super je velmi užitečné, pokud přepsáte metodu. Metoda brewCoffee BasicCoffeeMachine již zpracovává Kávuvýběr.FILTER_COFFEE a hodí CoffeeException pro nepodporované CoffeeSelections.

mohu to znovu použít v mé nové metodě brewCoffee. Místo toho, abych přeformuloval stejnou logiku, jen zkontroluji, zda je káva ESPRESSO. Pokud tomu tak není, používám Klíčové slovo super k volání metody brewCoffee superclass.,

zabraňte přepsání metody

Pokud se chcete ujistit, že žádná podtřída nemůže změnit implementaci metody, můžete ji prohlásit za konečnou. V tomto příkladu příspěvku jsem to udělal pro metodu addBeans třídy BasicCoffeeMachine.

je to často dobrý nápad, aby všechny metody konečné, které jsou volány konstruktorem. Zabraňuje jakékoli podtřídy, často neúmyslně, změně chování konstruktoru.,

podtřídy je také typ její nadtřídy

podtřídy dědí nejen atributy a metody z nadtřídy, ale to také dědí typy nadtřídy. V příkladu je Základnístroj typu BasicCoffeeMachine a objekt. A objekt PremiumCoffeeMachine je typu PremiumCoffeeMachine, BasicCoffeeMachine a objekt.

díky tomu můžete odevzdat objekt PremiumCoffeeMachine pro typ BasicCoffeeMachine.

BasicCoffeeMachinee coffeeMachine = (BasicCoffeeMachine) PremiumCoffeeMachine(beans);

, který vám umožní psát kód, který používá superclass a spustit jej se všemi podtřídy.,

v tomto příkladu se vrací kód metody createCoffeeMachine a metoda makeCoffee používá třídu BasicCoffeeMachine. Metoda createCoffeeMachine však instaluje nový objekt PremiumCoffeeMachine. Když se vrátí metodou, objekt je automaticky obsazen do BasicCoffeeMachine a kód může volat všechny veřejné metody třídy BasicCoffeeMachine.

objekt coffeeMachine dostane obsazení do BasicCoffeeMachine, ale je to stále PremiumCoffeeMachine., Takže když metoda makeCoffee volá metodu brewCoffee, nazývá metodu přepsanou na třídě PremiumCoffeeMachine.

definování abstraktních tříd

abstraktní třídy se liší od ostatních tříd, o kterých jsme mluvili. Mohou být prodlouženy, ale ne instantní. Díky tomu jsou ideální pro reprezentaci koncepčních zobecnění, která ve vaší konkrétní doméně neexistují, ale umožňují vám znovu použít části kódu.

pomocí abstraktního klíčového slova deklarujete třídu nebo metodu jako abstraktní. Abstraktní třída nemusí obsahovat žádné abstraktní metody., Abstraktní metoda však musí být deklarována abstraktní třídou.

pojďme refaktorovat příklad kávovaru a představit třídu AbstractCoffeeMachine jako podtřídu třídy BasicCoffeeMachine. Prohlašuji tuto třídu za abstraktní a definuji abstraktní metodu brewCoffee.

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; }

jak vidíte, neposkytuji tělo abstraktní metody brewCoffee. Jen to prohlašuji, jak bych to udělal v rozhraní., Když rozšíříte třídu AbstractCoffeeMachine, budete muset definovat podtřídu jako abstraktní nebo přepsat metodu brewCoffee k implementaci těla metody.

dělám drobné změny v základní třídě. Nyní rozšiřuje třídu AbstractCoffeeMachine a již existující metoda brewCoffee převažuje nad abstraktní metodou superclass.

Další věc, kterou jsem změnil, je Konstruktor třídy BasicCoffeeMachine. Teď to volání konstruktoru nadtřídy a přidává pár klíč-hodnota do configMap atribut bez použití Mapy., Je definována a instantována abstraktní superclass a může být použita ve všech podtříd.

jedná se o jeden z hlavních rozdílů mezi abstraktní superklasou a rozhraním. Abstraktní třída nejen umožňuje deklarovat metody, ale můžete také definovat atributy, které nejsou statické a konečné.

Shrnutí

Jak jste viděli, dědictví je silný koncept, který umožňuje realizovat podtřídy, které rozšiřuje nadtřídy. Tímto způsobem podtřída dědí všechny chráněné a veřejné atributy a metody a typy superclass., Pak můžete použít zděděné atributy nadtřídy, použít nebo přepsat zděděné metody, a obsazení podtřídy pro jakýkoliv typ své nadtřídy.

můžete použít abstraktní třídu k definování obecné abstrakce, kterou nelze instancovat. V rámci této třídy, můžete deklarovat abstraktní metody, které je třeba přepsat non-abstraktní podtřídy. To se často používá, pokud je implementace této metody specifická pro každou podtřídu, ale chcete definovat obecné API pro všechny třídy hierarchie.