„Amigo, îți plac balenele?”
"Balene? Nu, nu am auzit de ele."
"Este ca o vaca, doar mai mare și înoată. De altfel, balenele au venit de la vaci. A, sau cel puțin au un strămoș comun. Nu contează."
"Ascultă. Vreau să vă spun despre un alt instrument foarte puternic al POO: polimorfismul . Are patru caracteristici."
1) Anularea metodei.
Imaginează-ți că ai scris o clasă „Vaca” pentru un joc. Are o mulțime de variabile și metode membre. Obiectele acestei clase pot face diverse lucruri: să meargă, să mănânce, să doarmă. De asemenea, vacile sună un clopoțel când merg. Să presupunem că ați implementat totul în clasă până la cel mai mic detaliu.
Apoi, dintr-o dată, clientul spune că vrea să lanseze un nou nivel al jocului, în care toate acțiunile au loc în mare, iar personajul principal este o balenă.
Ați început să proiectați clasa Whale și vă dați seama că este doar puțin diferită de clasa Cow. Ambele clase folosesc o logică foarte similară și decideți să utilizați moștenirea.
Clasa Cow este ideală pentru a fi clasa părinte: are deja toate variabilele și metodele necesare. Tot ce trebuie să faceți este să adăugați capacitatea de a înota a balenei. Dar există o problemă: balena ta are picioare, coarne și un clopot. La urma urmei, clasa Cow implementează această funcționalitate. Ce poti face?
Depășirea metodei vine în ajutor. Dacă moștenim o metodă care nu face exact ceea ce avem nevoie în noua noastră clasă, putem înlocui metoda cu alta.
Cum se face asta? În clasa noastră descendentă, declarăm metoda pe care vrem să o schimbăm (cu aceeași semnătură a metodei ca în clasa părinte) . Apoi scriem cod nou pentru metodă. Asta este. Este ca și cum vechea metodă a clasei părinte nu ar exista.
Iată cum funcționează:
Cod | Descriere |
---|---|
|
Aici definim două clase: Cow și Whale . Whale moștenește Cow .
Clasa |
|
Acest cod afișează „ Sunt o vacă ” pe ecran. |
|
Acest cod afișează „ Sunt o balenă ” pe ecran |
După ce moștenește Cow
și înlocuiește printName
, Whale
clasa are de fapt următoarele date și metode:
Cod | Descriere |
---|---|
|
Nu știm nimic despre vreo metodă veche. |
— Sincer, la asta mă așteptam.
2) Dar asta nu este tot.
„Să presupunem că Cow
clasa are o printAll
metodă , care apelează celelalte două metode. Atunci codul ar funcționa astfel:”
Ecranul va afișa:
Sunt alb,
sunt o balenă
Cod | Descriere |
---|---|
|
|
|
Ecranul va afișa: Sunt alb, sunt o balenă |
Rețineți că atunci când metoda printAll () a clasei Cow este apelată pe un obiect Whale, va fi folosită metoda printName() a lui Whale, nu a lui Cow.
Important nu este clasa în care este scrisă metoda, ci mai degrabă tipul (clasa) obiectului pe care este apelată metoda.
"Înțeleg."
„Puteți moșteni și înlocui doar metodele non-statice. Metodele statice nu sunt moștenite și, prin urmare, nu pot fi suprascrise.”
Iată cum arată clasa Whale după ce aplicăm moștenirea și înlocuim metodele:
Cod | Descriere |
---|---|
|
Iată cum arată clasa Whale după ce aplicăm moștenirea și înlocuim metoda. Nu știm nimic despre vreo printName metodă veche. |
3) Tip turnare.
Iată un punct și mai interesant. Deoarece o clasă moștenește toate metodele și datele clasei sale părinte, un obiect al acestei clase poate fi referit de variabilele clasei părinte ( și părintele părintelui etc., până la clasa Object). Luați în considerare acest exemplu:
Cod | Descriere |
---|---|
|
Ecranul va afișa: Sunt alb. |
|
Ecranul va afișa: Sunt alb. |
|
Ecranul va afișa: Whale@da435a. Metoda toString() este moștenită din clasa Object. |
"Lucruri bune. Dar de ce ai avea nevoie de asta?"
"Este o caracteristică valoroasă. Veți înțelege mai târziu că este foarte, foarte valoroasă."
4) Legare tardivă (dispecerare dinamică).
Iată cum arată:
Cod | Descriere |
---|---|
|
Ecranul va afișa: Sunt o balenă. |
|
Ecranul va afișa: Sunt o balenă. |
Rețineți că nu tipul variabilei determină ce metodă specifică printName numim (cea a clasei Cow sau Whale), ci mai degrabă tipul de obiect referit de variabilă.
Variabila Cow stochează o referință la un obiect Whale , iar metoda printName definită în clasa Whale va fi apelată.
— Ei bine, nu au adăugat asta de dragul clarității.
"Da, nu este chiar atât de evident. Amintește-ți această regulă importantă:"
Setul de metode pe care le puteți apela la o variabilă este determinat de tipul variabilei. Dar ce metodă/implementare specifică este apelată este determinată de tipul/clasa obiectului referit de variabilă.
"Voi încerca."
„Veți întâlni asta în mod constant, așa că o veți înțelege rapid și nu uitați niciodată”.
5) Tip turnare.
Casting funcționează diferit pentru tipurile de referință, adică clase, decât pentru tipurile primitive. Cu toate acestea, conversiile de extindere și restrângere se aplică și tipurilor de referință. Luați în considerare acest exemplu:
Lărgirea conversiei | Descriere |
---|---|
|
O conversie clasică de lărgire. Acum puteți apela doar metode definite în clasa Cow pe obiectul Whale. Compilatorul vă va permite să utilizați variabila cow doar pentru a apela acele metode definite de tipul Cow. |
Îngustarea conversiei | Descriere |
---|---|
|
O conversie clasică de îngustare cu verificare de tip. Variabila cow de tip Cow stochează o referință la un obiect Whale. Verificăm dacă acesta este cazul și apoi efectuăm conversia de tip (lărgire). Aceasta se mai numește și turnare tip . |
|
De asemenea, puteți efectua o conversie de restrângere a unui tip de referință fără a verifica tipul obiectului. În acest caz, dacă variabila vacă indică spre altceva decât un obiect Whale, va fi aruncată o excepție (InvalidClassCastException). |
6) Și acum pentru ceva gustos. Apelarea metodei originale.
Uneori, când suprascrieți o metodă moștenită, nu doriți să o înlocuiți în întregime. Uneori vrei doar să adaugi puțin la el.
În acest caz, doriți cu adevărat ca codul noii metode să apeleze aceeași metodă, dar pe clasa de bază. Și Java hai să faci asta. Asa se face: super.method()
.
Aici sunt cateva exemple:
Cod | Descriere |
---|---|
|
|
|
Ecranul va afișa: Sunt alb Acest lucru este fals: Sunt o vacă Sunt o balenă |
"Hmm. Ei bine, asta a fost o lecție. Urechile mele de robot aproape s-au topit."
"Da, acestea nu sunt lucruri simple. Este unul dintre cele mai dificile materiale pe care le veți întâlni. Profesorul a promis că va oferi link-uri către materiale de la alți autori, astfel încât dacă tot nu înțelegeți ceva, puteți completa goluri.”
GO TO FULL VERSION