Clase interioare anonime și exemple - 1

"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:"

Exemplu de clasă interioară care moștenește clasa Thread
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:"

Cod
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
TigerThread thread = new TigerThread();

private class TigerThread extends Thread
{
 public void run()
 {
  tigerRun();
 }
}
Thread thread = new Thread()
{
 public void run()
 {
  tigerRun();
 }
};

„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
Cat tiger = new Tiger();

class Tiger extends Cat
{
}
Cat tiger = new Cat()
{
};

„Să explorăm din nou sintaxa:”

Declarația unei variabile Thread
Thread thread = new Thread();
Declarația unei variabile al cărei tip este „o clasă anonimă care moștenește 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:”

Declarația unei variabile Thread
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
Thread thread = new Thread()
{
  public void run()
  {
   printHi();
  }

  public void printHi()
  {
   System.out.println("Hi!");
  }
};
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
class Cat
{
 int x, y;
 Cat(int x, int y)
 {
  this.x = x;
  thix.y = y;
 }
}
Cat cat = new Cat(3,4)
{
  public void print()
  {
   System.out.println(x+" "+y);
  }
};

"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ă
Thread thread = new Thread()
{
  public void run()
  {
   tigerRun();
  }
};
TigerThread thread = new TigerThread();

private class TigerThread extends Thread
{
 public void run()
 {
  tigerRun();
 }
}
static Thread thread = new Thread()
{
  public void run()
  {
   tigerRun();
  }
};
static TigerThread thread = new TigerThread();

private class TigerThread extends Thread
{
 public void run()
 {
  tigerRun();
 }
}

"Î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."