Mga hindi kilalang panloob na klase, at mga halimbawa - 1

"Hi, Amigo!"

"Pero nag-hello na kami, Ellie!"

"Hoy, huwag kang makipagtalo sa tiyahin mo. Sa 31st century, kung mahigit kalahating oras ka nang hindi nagkikita, nakaugalian na naman ang kamustahin. Kaya huwag mo na akong bigyan ng ugali!"

"Anyway, oras na para sa isa pang interesanteng paksa: robot reproduction!"

"O_O."

"Biro lang, ang bagong paksa ay anonymous inner classes ."

"Sa Java, minsan may mga sitwasyon kung saan kakailanganin mo ang isang klase para magmana ng ilang klase. Dahil hindi sinusuportahan ng Java ang maramihang pamana, nalutas nila ang problemang ito gamit ang mga panloob na klase: sa aming klase, nagdedeklara kami ng isang panloob na klase at gumagawa ng ito ay nagmamana ng anumang klase na kailangan natin upang ito ay magmana. Narito ang isang halimbawa:"

Halimbawa ng isang panloob na klase na nagmamana ng klase ng 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();
  }
 }
}

"Maghukay tayo sa isa pang halimbawa:"

Kailangan namin ng subclass ng Thread class para ma-override ang run method nito."

"Iyon ang dahilan kung bakit sa klase ng Tiger idineklara namin ang panloob na klase ng TigerThread , na nagmamana ng Thread at nag-o-override sa paraan ng pagtakbo.

"Para sa kaginhawahan, tinukoy namin ang dalawang pamamaraan sa klase ng Tiger: tigerRun at startTiger (na kahalintulad sa mga pamamaraan ng pagtakbo at pagsisimula ng Thread."

"Sa pamamaraan ng tigerStart, lumikha kami ng isang bagay na TigerThread at hinihimok ang paraan ng pagsisimula() nito."

"Ang JVM ay lilikha ng isang bagong thread na magsisimulang tumakbo kapag tinawag ang pamamaraan ng pagtakbo ng TigerThread ."

"Ang pamamaraang ito ay tumatawag sa aming run method: tigerRun ."

"Nakapagtrabaho na ako sa mga thread dati, kaya parang diretso ito."

"Kailangan ba nating pangalanan ang mga pamamaraan na tigerRun at tigerStart?"

"Hindi, maaari sana naming tawagan silang tumakbo at magsimula, ngunit gusto ko ring ipakita na hindi namin namamana ang Thread. Maaaring mas nakakalito ang isang paliwanag."

"OK. Pagkatapos ay sa tingin ko nakuha ko ito. Ngunit kung ang tigerStart ay tinawag sa pangalawang pagkakataon, gagawa tayo at magsisimula ng pangalawang Thread object. Hindi ba't nangangahulugan iyon na magkakaroon tayo ng «isang tigre na tumatakbo sa dalawang magkaibang thread»? "

"Well, hindi ka ba matalas! Tama ka, at hindi iyon maganda. Isulat muli natin ang code na ganito:"

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

"It's not quite perfect. You still can't call a method like that twice. But this time, at least we won't create a second thread and make it seems like everything is fine."

"Tama. Sa pangalawang pagkakataon na magsimula ang isang Tigre, magkakaroon ka ng exception."

"Nakikita ko na ang mga pagkakamali na mas mahusay kaysa sa iyo, Ellie!"

"Yeah, you're doing great. Then let's move on to anonymous inner classes."

"Tandaan ang ilang aspeto ng code sa itaas:"

1) Namana namin ang klase ng Thread, ngunit halos walang code ang ipinatupad doon. "Ito ay higit pa «kinailangan naming magmana ng klase ng Thread» kaysa sa «minana namin ito upang palawigin ito».

2) Isang TigerThread object lang ang malilikha.

Sa madaling salita, sumulat kami ng isang buong bungkos ng code para lang ma-override ang isang paraan at lumikha ng isang bagay.

Naaalala mo ba kung paano ko pinag-usapan ang pag-imbento ng mga konstruktor?

Bago ang mga konstruktor Pagkatapos ng mga constructor
TigerThread thread = new TigerThread();

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

"Nakikita kong naging mas compact ang code, ngunit hindi ko masyadong naiintindihan kung ano ang nangyayari."

"Maaari nating pagsamahin ang apat na bagay sa isa:"

1) deklarasyon ng isang nagmula na klase

2) overriding ng pamamaraan

3) deklarasyon ng isang variable

4) paglikha ng isang instance ng isang nagmula na klase.

"Sa katunayan, ang ginagawa namin ay pagsasama-sama ng dalawang operasyon: pagdedeklara ng isang nagmula na klase at paggawa ng isang halimbawa ng klase na iyon."

Walang anonymous na klase Sa anonymous na klase
Cat tiger = new Tiger();

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

"I-explore natin muli ang syntax:"

Pagpapahayag ng isang variable ng Thread
Thread thread = new Thread();
Deklarasyon ng isang variable na ang uri ay «isang anonymous na klase na nagmamana ng Thread»
Thread thread = new Thread()
{

};

"Tandaan na hindi lang kami tumukoy ng bagong klase. Gumagawa kami ng variable—may tuldok-kuwit sa dulo!"

"At kung gusto nating i-override ang run method, kailangan nating isulat ito:"

Pagpapahayag ng isang variable ng Thread
Thread thread = new Thread()
{
 public void run()
  {
   System.out.println("new run-method");
  }
};

"Ang bilis mong mahuli. Magaling!"

"Salamat. Paano kung kailangan natin ng ibang pamamaraan na hindi bahagi ng klase ng Thread?"

"Maaari mong isulat ang mga ito."

"Bagaman hindi nagpapakilala, isa itong ganap na panloob na klase:"

Java code Paglalarawan
Thread thread = new Thread()
{
  public void run()
  {
   printHi();
  }

  public void printHi()
  {
   System.out.println("Hi!");
  }
};
Pula: code para sa paglikha ng variable.

Berde: code para sa paglikha ng bagay.

Asul: code para sa anonymous na nagmula na klase.

"Isang ganap na inner class?"

"Kaya maaari kong gamitin ang mga variable ng outer class?"

"Talagang."

"At may maipapasa ako sa constructor?"

"Oo, ngunit ang mga argumento lamang para sa constructor ng superclass:"

Klase Instance ng isang hindi kilalang panloob na klase
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);
  }
};

"Hindi namin maaaring idagdag ang aming sariling mga parameter sa tagabuo ng ibang tao. Ngunit maaari naming gamitin ang mga variable ng panlabas na klase, na mahusay na compensates para sa pagkukulang na ito."

"Paano kung kailangan ko pa talagang magdagdag ng iba pang mga parameter sa constructor?"

"Pagkatapos ay magdeklara ng isang ordinaryong (hindi-anonymous) na panloob na klase at gamitin iyon."

"Tama, muntik ko nang makalimutan yun."

"Paano kung magdeklara ako ng isang static na variable? Gagawin ba nito na ang anonymous na klase ay maging isang static na nested na klase sa halip na isang panloob na klase? Sa madaling salita, ito ba ay kulang ng reference sa panlabas na klase?"

"Hindi. Ito ay magiging isang hindi kilalang panloob na klase. Tingnan ang mga halimbawang ito."

Sa anonymous na klase Walang anonymous na klase
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();
 }
}

"Nakikita ko. Tanging ang static na variable ang magiging static, hindi ang klase."

"Oo."

"Sa katunayan, ang compiler ay gumagawa ng mga panloob na klase para sa lahat ng hindi kilalang panloob na mga klase. Ang mga klase na ito ay karaniwang pinangalanang «1», «2», «3», atbp."