Anonyme indre klasser og eksempler - 1

"Hei, Amigo!"

"Men vi har allerede sagt hei, Ellie!"

"Hei, ikke krangle med tanten din. I det 31. århundre, hvis du ikke har sett noen på mer enn en halv time, er det vanlig å si hei igjen. Så ikke gi meg din holdning!"

"I alle fall er det på tide med et annet interessant emne: robotreproduksjon!"

"O_O."

"Bare tuller, det nye emnet er anonyme indre klasser ."

"I Java er det noen ganger situasjoner der du trenger en klasse for å arve flere klasser. Siden Java ikke støtter multippel arv, har de løst dette problemet ved å bruke indre klasser: i klassen vår erklærer vi en indre klasse og lager den arver uansett hvilken klasse vi trenger den for å arve. Her er et eksempel:"

Eksempel på en indre klasse som arver trådklassen
class Tiger extends Cat
{
 public void tigerRun()
 {
  .....
 }

 public void startTiger()
 {
  TigerThread thread = new TigerThread();
  thread.start();
 }

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

"La oss grave i et annet eksempel:"

Vi trenger en underklasse av Thread-klassen for å overstyre dens kjøremetode."

"Det er derfor vi i Tiger-klassen erklærte den indre TigerThread- klassen, som arver Thread og overstyrer kjøremetoden.

"For enkelhets skyld definerte vi to metoder i Tiger-klassen: tigerRun og startTiger (som er analoge med Threads løpe- og startmetoder."

"I tigerStart-metoden lager vi et TigerThread- objekt og påkaller dets start()-metode."

"JVM vil opprette en ny tråd som vil begynne å kjøre når TigerThreads kjøremetode kalles."

"Denne metoden kaller deretter løpsmetoden vår : tigerRun . "

"Jeg har jobbet med tråder før, så dette virker enkelt."

"Må vi navngi metodene tigerRun og tigerStart?"

"Nei, vi kunne ha kalt dem løp og start, men jeg ville også demonstrere at vi ikke arver Tråd. En forklaring kan ha vært mer forvirrende."

"OK. Da tror jeg at jeg skjønner det. Men hvis tigerStart kalles en gang til, vil vi opprette og starte et andre Thread-objekt. Betyr ikke det at vi har «én tiger som kjører på to forskjellige tråder»? "

"Vel, er du ikke skarp! Du har rett, og det er ikke bra. La oss omskrive koden slik:"

Kode
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();
  }
 }
}

"Det er ikke helt perfekt. Du kan fortsatt ikke kalle en slik metode to ganger. Men denne gangen vil vi i det minste ikke lage en ny tråd og få det til å virke som om alt er bra."

"Det stemmer. Andre gang en Tiger startes, får du et unntak."

"Jeg oppdager allerede feil bedre enn deg, Ellie!"

"Ja, du gjør det bra. Så la oss gå videre til anonyme indre klasser."

"Vær oppmerksom på flere aspekter ved koden ovenfor:"

1) Vi arvet Thread-klassen, men implementerte praktisk talt ingen kode der. "Det var mer «vi måtte arve trådklassen» i stedet for «vi arvet den for å utvide den».

2) Bare ett TigerThread-objekt vil bli opprettet.

Med andre ord, vi skrev en hel haug med kode bare for å overstyre én metode og lage ett objekt.

Husker du hvordan jeg snakket om oppfinnelsen av konstruktører?

Før konstruktører Etter konstruktører
TigerThread thread = new TigerThread();

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

"Jeg ser at koden ble mer kompakt, men jeg forstår ikke helt hva som skjer."

"Vi kan kombinere fire ting til en:"

1) erklæring om en avledet klasse

2) metodeoverstyring

3) deklarering av en variabel

4) opprettelse av en forekomst av en avledet klasse.

"Det vi gjør er faktisk å kombinere to operasjoner: å erklære en avledet klasse og lage en forekomst av den klassen."

Uten anonym klasse Med anonym klasse
Cat tiger = new Tiger();

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

"La oss utforske syntaksen igjen:"

Erklæring av en trådvariabel
Thread thread = new Thread();
Erklæring av en variabel hvis type er «en anonym klasse som arver tråden»
Thread thread = new Thread()
{

};

"Merk at vi ikke bare definerer en ny klasse. Vi lager en variabel – det er et semikolon på slutten!"

"Og hvis vi vil overstyre kjøremetoden, må vi skrive dette:"

Erklæring av en trådvariabel
Thread thread = new Thread()
{
 public void run()
  {
   System.out.println("new run-method");
  }
};

"Du griper raskt. Godt gjort!"

"Takk. Hva om vi trenger andre metoder som ikke er en del av trådklassen?"

"Du kan skrive dem."

"Selv om dette er anonymt, er dette en fullverdig indre klasse:"

Java-kode Beskrivelse
Thread thread = new Thread()
{
  public void run()
  {
   printHi();
  }

  public void printHi()
  {
   System.out.println("Hi!");
  }
};
Rød: kode for å lage variabelen.

Grønn: kode for å lage objektet.

Blå: kode for den anonyme avledede klassen.

"En fullverdig indre klasse?"

"Så jeg kan bruke variablene til den ytre klassen?"

"Absolutt."

"Og jeg kan gi noe til konstruktøren?"

"Ja, men bare argumentene for superklassens konstruktør:"

Klasse Forekomst av en anonym indre klasse
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);
  }
};

"Vi kan ikke legge til våre egne parametere til noen andres konstruktør. Men vi kan bruke variablene til den ytre klassen, som godt kompenserer for denne mangelen."

"Hva om jeg fortsatt trenger å legge til andre parametere til konstruktøren?"

"Så erklær en vanlig (ikke-anonym) indre klasse og bruk den."

"Akk, jeg glemte nesten det."

"Hva om jeg erklærer en statisk variabel? Vil det gjøre at den anonyme klassen blir en statisk nestet klasse i stedet for en indre klasse? Med andre ord, vil den mangle en referanse til den ytre klassen?"

"Nei. Det ville vært en anonym indre klasse. Se på disse eksemplene."

Med anonym klasse Uten anonym klasse
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();
 }
}

"Jeg skjønner. Bare den statiske variabelen ville være statisk, ikke klassen."

"Japp."

"Faktisk oppretter kompilatoren indre klasser for alle anonyme indre klasser. Disse klassene heter vanligvis «1», «2», «3» osv.»