– Amigo, szereted a bálnákat?
"Bálnák? Nem, soha nem hallottam róluk."
"Olyan, mint egy tehén, csak nagyobb és úszik. Mellesleg a bálnák tehenektől származtak. Uh, vagy legalábbis közös ősük van. Nem számít."
"Figyelj ide. Az OOP egy másik nagyon hatékony eszközéről szeretnék beszélni: a polimorfizmusról . Négy jellemzője van."
1) A módszer felülbírálása.
Képzeld el, hogy írtál egy „Tehén” osztályt egy játékhoz. Sok tagváltozója és metódusa van. Ennek az osztálynak az objektumai sokféle dolgot tudnak tenni: sétálni, enni, aludni. A tehenek is harangoznak, amikor sétálnak. Tegyük fel, hogy a legapróbb részletekig mindent megvalósított az osztályban.
Aztán hirtelen az ügyfél azt mondja, hogy a játék egy új szintjét akarja kiadni, ahol minden akció a tengerben történik, és a főszereplő egy bálna.
Elkezdted tervezni a Bálna osztályt, és rájöttél, hogy ez csak egy kicsit különbözik a Cow osztálytól. Mindkét osztály nagyon hasonló logikát használ, és Ön az öröklődés mellett dönt.
A Cow osztály ideálisan alkalmas szülő osztálynak: már minden szükséges változóval és metódussal rendelkezik. Mindössze annyit kell tennie, hogy hozzáadja a bálna úszási képességét. De van egy probléma: a bálnádnak lábai, szarvai és harangja van. Végül is a Cow osztály valósítja meg ezt a funkciót. Mit tudsz csinálni?
A módszer felülbírálása segít. Ha olyan metódust örökölünk, amely nem pontosan azt csinálja, amire szükségünk van az új osztályunkban, akkor a metódust lecserélhetjük egy másikra.
Hogyan történik ez? A leszármazott osztályunkban deklaráljuk a módosítani kívánt metódust (ugyanaz a metódus aláírással, mint a szülő osztályban) . Ezután új kódot írunk a metódushoz. Ez az. Mintha nem létezne a szülő osztály régi metódusa.
Így működik:
Kód | Leírás |
---|---|
|
Itt két osztályt határozunk meg: Cow és Whale . Whale örököl Cow .
Az |
|
Ez a kód a „ tehén vagyok ” feliratot jeleníti meg a képernyőn. |
|
Ez a kód az „ I'm a bálna ” feliratot jeleníti meg a képernyőn |
Miután örökli Cow
és felülírja printName
, az Whale
osztály valójában a következő adatokkal és metódusokkal rendelkezik:
Kód | Leírás |
---|---|
|
Egyetlen régi módszerről sem tudunk semmit. |
– Őszintén szólva, erre számítottam.
2) De ez még nem minden.
"Tegyük fel, hogy az Cow
osztálynak van egy printAll
, metódusa, amely meghívja a másik két metódust. Ekkor a kód így működne:"
A képernyőn megjelenik:
fehér vagyok,
bálna vagyok
Kód | Leírás |
---|---|
|
|
|
A képernyőn megjelenik: fehér vagyok, bálna vagyok |
Ne feledje, hogy amikor a Cow osztály printAll () metódusát hívják meg egy Whale objektumon, akkor a Whale printName() metódusa lesz használatos, nem a Cow's.
Nem az a fontos, hogy a metódus melyik osztályba van írva, hanem az objektum típusa (osztálya), amelyen a metódus meghívódik.
"Látom."
"Csak nem statikus módszereket örökölhet és írhat felül. A statikus módszerek nem öröklődnek, ezért nem bírálhatók felül."
Így néz ki a Whale osztály az öröklődés alkalmazása és a metódusok felülírása után:
Kód | Leírás |
---|---|
|
Így néz ki a Whale osztály az öröklődés alkalmazása és a metódus felülírása után. Egyetlen régi módszerről sem tudunk semmit printName . |
3) Típusöntés.
Itt van egy még érdekesebb pont. Mivel egy osztály örökli szülőosztályának összes metódusát és adatát, ennek az osztálynak az objektumára a szülő osztály változói (és a szülő szülője stb., egészen az Object osztályig) hivatkozhatnak . Tekintsük ezt a példát:
Kód | Leírás |
---|---|
|
A képernyőn megjelenik: fehér vagyok. |
|
A képernyőn megjelenik: fehér vagyok. |
|
A képernyőn megjelenik: Whale@da435a. A toString() metódus az Object osztályból öröklődik. |
"Jó cucc. De miért van erre szükséged?"
"Ez egy értékes tulajdonság. Később meg fogod érteni, hogy nagyon-nagyon értékes."
4) Késői kötés (dinamikus feladás).
Így néz ki:
Kód | Leírás |
---|---|
|
A képernyőn megjelenik: Bálna vagyok. |
|
A képernyőn megjelenik: Bálna vagyok. |
Megjegyezzük, hogy nem a változó típusa határozza meg, hogy melyik printName metódust hívjuk meg (a Cow vagy a Whale osztályét), hanem a változó által hivatkozott objektum típusa.
A Cow változó egy Whale objektumra való hivatkozást tárol, és a Whale osztályban meghatározott printName metódus kerül meghívásra.
– Nos, ezt nem a tisztánlátás kedvéért tették hozzá.
"Igen, ez nem olyan nyilvánvaló. Ne feledje ezt a fontos szabályt:"
A változóhoz meghívható metódusok halmazát a változó típusa határozza meg. De hogy melyik konkrét metódust/implementációt hívják meg, azt a változó által hivatkozott objektum típusa/osztálya határozza meg.
"Megpróbálom."
– Állandóan ebbe fog belefutni, így gyorsan megérti, és soha nem felejti el.
5) Típusöntés.
Az öntvény másként működik referenciatípusoknál, azaz osztályoknál, mint a primitív típusoknál. A szélesítő és szűkítő konverziók azonban vonatkoznak a referenciatípusokra is. Tekintsük ezt a példát:
Konverzió szélesítése | Leírás |
---|---|
|
Klasszikus szélesítő átalakítás. Most már csak a Cow osztályban meghatározott metódusokat hívhatja meg a Whale objektumon. A fordító csak a Cow típus által meghatározott metódusok meghívására engedi meg a cow változó használatát. |
Konverzió szűkítése | Leírás |
---|---|
|
Klasszikus szűkítő konverzió típusellenőrzéssel . A Cow típusú tehén változó egy bálna objektumra való hivatkozást tárol . Ellenőrizzük, hogy ez így van-e , majd végrehajtjuk a (kiszélesítő) típuskonverziót. Ezt típusöntésnek is nevezik . |
|
A referenciatípus szűkítő átalakítása az objektum típusellenőrzése nélkül is elvégezhető. Ebben az esetben, ha a tehén változó valami másra mutat, mint egy Whale objektumra, kivételt (InvalidClassCastException) dob a rendszer. |
6) És most valami finomat. Az eredeti módszer meghívása.
Néha egy örökölt módszer felülbírálásakor nem akarja teljesen lecserélni. Néha csak egy kicsit szeretne hozzátenni.
Ebben az esetben valóban azt szeretné, hogy az új metódus kódja ugyanazt a metódust hívja meg, de az alaposztályon. És Java hadd csináld ezt. Ez így történik: super.method()
.
Íme néhány példa:
Kód | Leírás |
---|---|
|
|
|
A képernyőn megjelenik: fehér vagyok Ez hamis: tehén vagyok, bálna vagyok |
"Hmm. Nos, ez egy lecke volt. A robotfülem majdnem elolvadt."
"Igen, ez nem egyszerű dolog. Ez az egyik legnehezebb anyag, amivel találkozni fogsz. A professzor megígérte, hogy linkeket ad más szerzők anyagaihoz, hogy ha még mindig nem értesz valamit, akkor kitöltheted a rések."
GO TO FULL VERSION