Útmutató az öröklődéshez a Java-ban

1. Áttekintés

Az objektum-orientált programozás egyik alapelve - öröklés - lehetővé teszi számunkra a meglévő kód újrafelhasználását vagy egy meglévő típus kibővítését.

Egyszerűen fogalmazva: a Java-ban egy osztály örökölhet egy másik osztályt és több interfészt, míg egy interfész más interfészeket is.

Ebben a cikkben az öröklés szükségességével kezdjük, áttérve arra, hogy az öröklés hogyan működik osztályokkal és interfészekkel.

Ezután kitérünk arra, hogy a változó / metódus nevek és a hozzáférés-módosítók hogyan befolyásolják az öröklődő tagokat.

És a végén meglátjuk, mit jelent egy típus öröklése.

2. Az öröklés szükségessége

Képzelje el, hogy autógyártóként több autómodellt kínál az ügyfeleknek. Annak ellenére, hogy a különböző autómodellek különböző funkciókat kínálhatnak, például napfénytetőt vagy golyóálló ablakokat, mindegyik tartalmazna közös alkatrészeket és jellemzőket, például a motort és a kerekeket.

Van értelme hozzon létre egy alaptervet és bővítse ki speciális verzióik létrehozásához, ahelyett, hogy az egyes autómodelleket külön-külön terveznénk, a semmiből.

Hasonló módon, örökléssel létrehozhatunk egy osztályt, amely alapvető jellemzőkkel és viselkedéssel rendelkezik, és létrehozhatunk speciális változatokat osztályok létrehozásával, amelyek öröklik ezt az alaposztályt. Az interfészek ugyanúgy kibővíthetik a meglévő interfészeket.

Észre fogjuk venni, hogy több kifejezés használ egy olyan típust, amelyet egy másik típus örököl, különösen:

  • az alaptípust szuper- vagy szülőtípusnak is nevezik
  • egy származtatott típust kiterjesztett, al- vagy gyermektípusnak nevezzük

3. Osztályos öröklés

3.1. Osztály kiterjesztése

Egy osztály örökölhet egy másik osztályt, és további tagokat határozhat meg.

Kezdjük egy alaposztály meghatározásával Autó:

közosztályú Car {int kerekek; Vonós modell; void start () {// Alapvető részek ellenőrzése}}

Osztály Páncélozott autó örökölheti a tagjait Autó osztály által a kulcsszó használatával kiterjed nyilatkozatában:

közkategóriás ArmoredCar kiterjeszti a Car {int bulletProofWindows; void remoteStartCar () {// ezt a járművet egy távirányítóval lehet elindítani}}

Most azt mondhatjuk, hogy a Páncélozott autó osztály az alosztálya Autó, és ez utóbbi szuperosztálya Páncélozott autó.

A Java osztályok támogatják az egyszeri öröklést; a Páncélozott autó osztály nem bővíthet több osztályt.

Ezenkívül vegye figyelembe, hogy anélkül kiterjed kulcsszó, egy osztály implicit módon örökli az osztályt java.lang.Tárgy.

Egy alosztály osztály örökli a nem statikusat védett és nyilvános tagok a szuperosztályból. Ezen kívül a tagok alapértelmezett és csomag a hozzáférés öröklődik, ha a két osztály ugyanabban a csomagban van.

Másrészt a magán és statikus egy osztály tagjai nem öröklődnek.

3.2. Hozzáférés a szülő tagokhoz egy gyermekosztályból

Az örökölt tulajdonságok vagy módszerek eléréséhez egyszerűen használhatjuk őket közvetlenül:

public class ArmoredCar kiterjeszti Car {public String registerModel () {return model; }}

Vegye figyelembe, hogy a tagok eléréséhez nincs szükségünk a szuperosztályra való hivatkozásra.

4. Interfész öröklődése

4.1. Több interfész megvalósítása

Bár az osztályok csak egy osztályt örökölhetnek, több interfészt is megvalósíthatnak.

Képzelje el a Páncélozott autó hogy az előző szakaszban meghatároztuk, szükséges egy szuper kémhez. Így a Autó a gyártó cég úgy gondolta, hogy hozzáadja a repülő és az úszó funkciókat:

nyilvános felület Úszó {void floatOnWater (); }
nyilvános felület Flyable {void fly (); }
public class ArmoredCar kiterjeszti az autóeszközöket Úszó, Repülhető {public void floatOnWater () {System.out.println ("Tudok lebegni!"); } public void fly () {System.out.println ("Tudok repülni!"); }}

A fenti példában észrevesszük a kulcsszó használatát megvalósítja felületről örökölni.

4.2. A többszörös öröklés kérdései

A Java többféle öröklést tesz lehetővé interfészek használatával.

A Java 7-ig ez nem volt kérdés. Az interfészek csak meghatározni tudták absztrakt módszerek, vagyis megvalósítás nélküli módszerek. Tehát, ha egy osztály több interfészt valósított meg ugyanazzal a módszeraláírással, akkor nem jelentett problémát. A megvalósító osztálynak végül csak egyetlen módszere volt a megvalósításra.

Lássuk, hogyan változott ez az egyszerű egyenlet a alapértelmezett metódusok interfészekben, Java 8-tal.

A Java 8-tól kezdve az interfészek dönthetnek úgy, hogy meghatározzák az alapértelmezett megvalósításokat a módszereihez (egy interfész továbbra is meghatározhatja absztrakt mód). Ez azt jelenti, hogy ha egy osztály több interfészt valósít meg, amelyek azonos aláírású módszereket határoznak meg, a gyermekosztály külön megvalósításokat örökölne. Ez összetettnek hangzik, és nem megengedett.

A Java nem engedélyezi ugyanazon módszerek több megvalósításának öröklődését, külön interfészekben definiálva.

Íme egy példa:

nyilvános felület Úszó {alapértelmezett void repair () {System.out.println ("Úszó tárgy javítása"); }}
nyilvános felület Flyable {alapértelmezett void repair () {System.out.println ("Flyable objektum javítása"); }}
A közkategóriás ArmoredCar meghosszabbítja az autóeszközöket Úszó, Repülhető {// ez nem áll össze}

Ha mindkét felületet meg akarjuk valósítani, akkor felül kell írnunk a javítás() módszer.

Ha az előző példák interfészei azonos nevű változókat határoznak meg, mondjuk időtartamát, nem érhetjük el őket anélkül, hogy a változó nevét megadnánk az interfész nevével:

nyilvános felület Úszó {int duration = 10; }
nyilvános felület Repülhető {int időtartama = 20; }
a Public Class ArmoredCar kiterjeszti az autóeszközöket Úszó, Repülhető {public void aMethod () {System.out.println (időtartam); // nem fordítja le a System.out.println (Floatable.duration); // kimeneti 10 System.out.println (Flyable.duration); // kimenetek 20}}

4.3. Interfészek más interfészek kiterjesztése

Egy interfész több interfészt is kiterjeszthet. Íme egy példa:

nyilvános felület Úszó {void floatOnWater (); }
interfész interfész Flyable {void fly (); }
nyilvános felület A SpaceTraveller kiterjeszti az Úszó, Repülhető {void remoteControl (); }

Az interfész a kulcsszó használatával örököl más interfészeket kiterjed. Az osztályok a kulcsszót használják megvalósítja interfész öröklésére.

5. Öröklődő típus

Ha egy osztály egy másik osztályt vagy interfészeket örököl, a tagok öröklésén kívül a típusukat is örökli. Ez vonatkozik egy olyan felületre is, amely más interfészeket örököl.

Ez egy nagyon erős koncepció, amely lehetővé teszi a fejlesztők számára program egy interfészre (alaposztály vagy interfész), nem pedig a megvalósításuk programozása.

Képzeljünk el például egy olyan állapotot, amikor egy szervezet listát vezet az alkalmazottak tulajdonában lévő autókról. Természetesen minden alkalmazott különböző autómodellekkel rendelkezhet. Tehát hogyan hivatkozhatunk különböző autós esetekre? Itt van a megoldás:

public class Alkalmazott {private String név; személygépkocsi; // standard konstruktor}

Mivel az összes származtatott osztály Autó örökölje a típust Autó, a származtatott osztálypéldányokat az osztály változójának felhasználásával lehet hivatkozni Autó:

E1 alkalmazott = új alkalmazott ("Shreya", új ArmoredCar ()); E2 = új alkalmazott ("Paul", új SpaceCar ()); E3 alkalmazott = új alkalmazott ("Pavni", új BMW ());

6. Rejtett osztálytagok

6.1. Rejtett példányú tagok

Mi történik, ha mind a szuperosztály, mind az alosztály azonos nevű változót vagy metódust határoz meg? Ne aggódj; továbbra is hozzáférhetünk mindkettőhöz. Mindazonáltal egyértelművé kell tennünk szándékunkat a Java számára a változó vagy a metódus előtaggal történő ellátásával ez vagy szuper.

A ez kulcsszó arra a példányra utal, amelyben használják. A szuper kulcsszó (mivel nyilvánvalónak tűnik) a szülő osztály példányára utal:

nyilvános osztályú ArmoredCar kiterjeszti a Car {private String modellt; public String getAValue () {return szupermodell; // visszaadja a Car alaposztályban definiált modell értékét // return this.model; // visszaadja az ArmoredCar-ban definiált modell értékét // return model; // visszaadja az ArmoredCar-ban definiált modell értékét}}

Sok fejlesztő használja ez és szuper kulcsszavak, amelyek kifejezetten megadják, melyik változóra vagy módszerre hivatkoznak. Ha azonban minden taggal együtt használjuk őket, akkor a kódunk rendetlen lehet.

6.2. Rejtett statikus tagok

Mi történik amikor az alaposztályunk és az alosztályaink statikus változókat és módszereket határoznak meg azonos néven? Hozzáférhetünk a statikus tag az alaposztályból, a származtatott osztályban, ahogyan a példányváltozóknál tesszük?

Nézzük meg egy példával:

public class Car {public static String msg () {return "Autó"; }}
Public class ArmoredCar kiterjeszti Car {public static String msg () {return super.msg (); // ez nem áll össze. }}

Nem, nem tehetjük. A statikus tagok egy osztályhoz tartoznak, nem pedig példányokhoz. Tehát nem használhatjuk a nem statikusat szuper kulcsszó msg ().

Mivel a statikus tagok egy osztályhoz tartoznak, az előző hívást a következőképpen módosíthatjuk:

vissza Car.msg ();

Tekintsük a következő példát, amelyben az alaposztály és a levezetett osztály egyaránt statikus módszert határoz meg msg () ugyanazzal az aláírással:

public class Car {public static String msg () {return "Autó"; }}
public class ArmoredCar kiterjeszti Car {public static String msg () {return "ArmoredCar"; }}

Így hívhatjuk őket:

Első autó = új ArmoredCar (); ArmoredCar second = új ArmoredCar ();

Az előző kódhoz first.msg () kinyomtatja: „Autó és second.msg () „ArmoredCar” -t ad ki. A meghívott statikus üzenet a hivatkozásra használt változó típusától függ Páncélozott autó példa.

7. Következtetés

Ebben a cikkben a Java nyelv alapvető aspektusával - az örökléssel - foglalkoztunk.

Láttuk, hogy a Java hogyan támogatja az egyszeri öröklést osztályokkal és a többszörös öröklést interfészekkel, és megvitattuk a mechanizmus bonyolultságát a nyelven.

Mint mindig, a példák teljes forráskódja elérhető a GitHubon.