"Bună, Amigo!"
— Dar deja am salutat, Ellie!
"Hei, nu te certa cu mătușa ta. În secolul 31, dacă nu te-ai mai văzut pe cineva de mai bine de jumătate de oră, se obișnuiește să te saluti din nou. Așa că nu-mi da atitudinea ta!"
„Oricum, este timpul pentru un alt subiect interesant: reproducerea robotului!”
"O_O."
„Glumesc, noul subiect sunt clasele interioare anonime .”
„În Java, uneori există situații în care veți avea nevoie de o clasă pentru a moșteni mai multe clase. Deoarece Java nu acceptă moștenirea multiplă, au rezolvat această problemă folosind clase interne: în clasa noastră, declarăm o clasă interioară și facem moștenește orice clasă pe care trebuie să o moștenim. Iată un exemplu:"
class Tiger extends Cat
{
public void tigerRun()
{
.....
}
public void startTiger()
{
TigerThread thread = new TigerThread();
thread.start();
}
class TigerThread extends Thread
{
public void run()
{
tigerRun();
}
}
}
„Hai să cercetăm un alt exemplu:”
Avem nevoie de o subclasă a clasei Thread pentru a-i suprascrie metoda de rulare.”
„De aceea, în clasa Tiger am declarat clasa interioară TigerThread , care moștenește Thread și suprascrie metoda run.
„Pentru comoditate, am definit două metode în clasa Tiger: tigerRun și startTiger (care sunt analoge cu metodele de rulare și pornire ale Thread."
„În metoda tigerStart, creăm un obiect TigerThread și invocăm metoda lui start()”.
„JVM-ul va crea un fir nou care va începe să ruleze când este apelată metoda de rulare a lui TigerThread .”
„Această metodă apelează apoi metoda noastră de rulare : tigerRun ”.
„Am mai lucrat cu fire, așa că pare simplu.”
„Trebuie să denumim metodele tigerRun și tigerStart?”
„Nu, i-am fi putut chema să alerge și să înceapă, dar am vrut, de asemenea, să demonstrez că nu moștenim Thread. O explicație ar fi putut fi mai confuză.”
„OK. Atunci cred că am înțeles. Dar dacă tigerStart este apelat a doua oară, vom crea și vom începe un al doilea obiect Thread. Asta nu înseamnă că vom avea „un tigru care rulează pe două fire diferite”? "
"Ei bine, nu ești ascuțit! Ai dreptate și asta nu e bine. Hai să rescriem codul așa:"
class Tiger extends Cat
{
public void tigerRun()
{
.....
}
public void startTiger()
{
thread.start();
}
private TigerThread thread = new TigerThread();
private class TigerThread extends Thread
{
public void run()
{
tigerRun();
}
}
}
"Nu este perfect. Totuși nu poți apela de două ori o astfel de metodă. Dar de data aceasta, cel puțin nu vom crea un al doilea thread și nu vom face să pară că totul este în regulă."
"Așa este. A doua oară când pornește un Tigru, vei primi o excepție."
— Deja observ greşelile mai bine decât tine, Ellie!
"Da, te descurci grozav. Atunci hai să trecem la clasele interioare anonime."
„Rețineți câteva aspecte ale codului de mai sus:”
1) Am moștenit clasa Thread, dar nu am implementat practic niciun cod acolo. „A fost mai degrabă „trebuia să moștenim clasa Thread” decât „am moștenit-o pentru a o extinde”.
2) Va fi creat un singur obiect TigerThread.
Cu alte cuvinte, am scris o grămadă de cod doar pentru a suprascrie o metodă și a crea un obiect.
Îți amintești cum vorbeam despre invenția constructorilor?
Înainte de constructori | După constructori |
---|---|
|
|
„Văd că codul a devenit mai compact, dar nu prea înțeleg ce se întâmplă”.
„Putem combina patru lucruri într-unul singur:”
1) declararea unei clase derivate
2) depășirea metodei
3) declararea unei variabile
4) crearea unei instanțe a unei clase derivate.
„De fapt, ceea ce facem este să combinăm două operații: declararea unei clase derivate și crearea unei instanțe a acelei clase.”
Fără clasă anonimă | Cu clasa anonima |
---|---|
|
|
„Să explorăm din nou sintaxa:”
Thread thread = new Thread();
Thread thread = new Thread()
{
};
"Rețineți că nu definim pur și simplu o nouă clasă. Creăm o variabilă - există un punct și virgulă la sfârșit!"
„Și dacă vrem să suprascriem metoda de rulare, atunci trebuie să scriem asta:”
Thread thread = new Thread()
{
public void run()
{
System.out.println("new run-method");
}
};
"Te prinzi repede. Bravo!"
"Multumesc. Ce se intampla daca avem nevoie de alte metode care nu fac parte din clasa Thread?"
„Le poți scrie”.
„Deși anonim, aceasta este o clasă interioară cu drepturi depline:”
Cod Java | Descriere |
---|---|
|
Roșu: cod pentru crearea variabilei.
Verde: cod pentru crearea obiectului. Albastru: cod pentru clasa derivată anonimă. |
— O clasă interioară cu drepturi depline?
„Deci pot folosi variabilele clasei exterioare?”
"Absolut."
— Și pot să transmit ceva constructorului?
„Da, dar numai argumentele pentru constructorul superclasei:”
Clasă | Instanța unei clase interioare anonime |
---|---|
|
|
"Nu putem adăuga propriii parametri la constructorul altcuiva. Dar putem folosi variabilele clasei exterioare, ceea ce compensează frumos acest neajuns."
„Dacă mai trebuie să adaug alți parametri la constructor?”
„Atunci declarați o clasă interioară obișnuită (non-anonimă) și folosiți-o.”
— Corect, aproape că am uitat de asta.
"Ce se întâmplă dacă declar o variabilă statică? Ar face ca clasa anonimă să devină o clasă imbricată statică mai degrabă decât o clasă interioară? Cu alte cuvinte, îi va lipsi o referință la clasa exterioară?"
"Nu. Ar fi o clasă interioară anonimă. Uită-te la aceste exemple."
Cu clasa anonima | Fără clasă anonimă |
---|---|
|
|
|
|
"Înțeleg. Numai variabila statică ar fi statică, nu clasa."
"Da."
„De fapt, compilatorul creează clase interne pentru toate clasele interne anonime. Aceste clase sunt de obicei numite «1», «2», «3», etc."
GO TO FULL VERSION