Kelas dalaman tanpa nama, dan contoh - 1

"Hai, Amigo!"

"Tetapi kami sudah bertanya khabar, Ellie!"

"Hei, jangan bertengkar dengan makcik. Dalam abad ke-31 ni, kalau dah lebih setengah jam tak jumpa orang, biasalah bagi salam lagi. Jadi jangan bagi perangai awak!"

"Apa pun, sudah tiba masanya untuk topik menarik lain: pembiakan robot!"

"O_O."

"Hanya bergurau, topik baharu ialah kelas dalaman tanpa nama ."

"Di Jawa, kadangkala terdapat situasi di mana anda memerlukan kelas untuk mewarisi beberapa kelas. Memandangkan Java tidak menyokong warisan berbilang, mereka telah menyelesaikan masalah ini menggunakan kelas dalam: dalam kelas kami, kami mengisytiharkan kelas dalam dan membuat ia mewarisi apa sahaja kelas yang kita perlukan untuk diwarisi. Berikut ialah contoh:"

Contoh kelas dalam yang mewarisi kelas 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();
  }
 }
}

"Mari kita gali contoh lain:"

Kami memerlukan subkelas kelas Thread untuk mengatasi kaedah lariannya."

"Itulah sebabnya dalam kelas Tiger kami mengisytiharkan kelas dalam TigerThread , yang mewarisi Thread dan mengatasi kaedah larian.

"Untuk kemudahan, kami mentakrifkan dua kaedah dalam kelas Tiger: tigerRun dan startTiger (yang serupa dengan kaedah run and start Thread."

"Dalam kaedah tigerStart, kami mencipta objek TigerThread dan menggunakan kaedah start()nya."

"JVM akan mencipta benang baharu yang akan mula berjalan apabila kaedah larian TigerThread dipanggil."

"Kaedah ini kemudiannya memanggil kaedah larian kami : tigerRun ."

"Saya pernah bekerja dengan benang sebelum ini, jadi ini nampaknya mudah."

"Adakah kita perlu menamakan kaedah tigerRun dan tigerStart?"

"Tidak, kami boleh memanggil mereka lari dan mula, tetapi saya juga mahu menunjukkan bahawa kami tidak mewarisi Thread. Penjelasan mungkin lebih mengelirukan."

"OK. Kemudian saya rasa saya faham. Tetapi jika tigerStart dipanggil untuk kali kedua, kita akan mencipta dan memulakan objek Thread kedua. Bukankah itu bermakna kita akan mempunyai «satu harimau berjalan pada dua benang berbeza»? "

"Nah, bukankah anda tajam! Anda betul, dan itu tidak bagus. Mari kita tulis semula kod seperti ini:"

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

"Ia tidak begitu sempurna. Anda masih tidak boleh memanggil kaedah seperti itu dua kali. Tetapi kali ini, sekurang-kurangnya kami tidak akan mencipta benang kedua dan menjadikannya kelihatan seperti semuanya baik-baik saja."

"Betul. Kali kedua Harimau dimulakan, kamu akan mendapat pengecualian."

"Saya sudah nampak kesilapan lebih baik daripada awak, Ellie!"

"Ya, anda hebat. Kemudian mari kita beralih ke kelas dalaman tanpa nama."

"Perhatikan beberapa aspek kod di atas:"

1) Kami mewarisi kelas Thread, tetapi melaksanakan secara praktikal tiada kod di sana. "Ia lebih banyak «kami terpaksa mewarisi kelas Thread» daripada «kami mewarisinya untuk melanjutkannya».

2) Hanya satu objek TigerThread akan dibuat.

Dalam erti kata lain, kami menulis sekumpulan kod hanya untuk mengatasi satu kaedah dan mencipta satu objek.

Adakah anda masih ingat bagaimana saya bercakap tentang ciptaan pembina?

Sebelum pembina Selepas pembina
TigerThread thread = new TigerThread();

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

"Saya lihat kod itu menjadi lebih padat, tetapi saya tidak begitu faham apa yang berlaku."

"Kita boleh menggabungkan empat perkara menjadi satu:"

1) pengisytiharan kelas terbitan

2) kaedah mengatasi

3) pengisytiharan pembolehubah

4) penciptaan contoh kelas terbitan.

"Malah, apa yang kami lakukan ialah menggabungkan dua operasi: mengisytiharkan kelas terbitan dan mencipta contoh kelas itu."

Tanpa kelas tanpa nama Dengan kelas tanpa nama
Cat tiger = new Tiger();

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

"Mari kita terokai sintaks sekali lagi:"

Pengisytiharan pembolehubah Benang
Thread thread = new Thread();
Pengisytiharan pembolehubah yang jenisnya ialah «kelas tanpa nama yang mewarisi Thread»
Thread thread = new Thread()
{

};

"Perhatikan bahawa kami bukan sekadar mentakrifkan kelas baharu. Kami sedang mencipta pembolehubah—ada koma bertitik di hujungnya!"

"Dan jika kita ingin mengatasi kaedah larian, maka kita perlu menulis ini:"

Pengisytiharan pembolehubah Benang
Thread thread = new Thread()
{
 public void run()
  {
   System.out.println("new run-method");
  }
};

"Kau cepat tangkap. Syabas!"

"Terima kasih. Bagaimana jika kita memerlukan kaedah lain yang bukan sebahagian daripada kelas Thread?"

"Anda boleh menulisnya."

"Walaupun tanpa nama, ini adalah kelas dalaman yang lengkap:"

kod Java Penerangan
Thread thread = new Thread()
{
  public void run()
  {
   printHi();
  }

  public void printHi()
  {
   System.out.println("Hi!");
  }
};
Merah: kod untuk mencipta pembolehubah.

Hijau: kod untuk mencipta objek.

Biru: kod untuk kelas terbitan tanpa nama.

"Kelas dalaman yang lengkap?"

"Jadi saya boleh menggunakan pembolehubah kelas luar?"

"Sama sekali."

"Dan saya boleh menyampaikan sesuatu kepada pembina?"

"Ya, tetapi hanya hujah untuk pembina superclass:"

Kelas Contoh kelas dalaman tanpa nama
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);
  }
};

"Kami tidak boleh menambah parameter kami sendiri kepada pembina orang lain. Tetapi kami boleh menggunakan pembolehubah kelas luar, yang mengimbangi dengan baik kekurangan ini."

"Bagaimana jika saya masih perlu menambah parameter lain pada pembina?"

"Kemudian isytiharkan kelas dalaman biasa (bukan tanpa nama) dan gunakan itu."

"Betul, saya hampir terlupa tentang itu."

"Bagaimana jika saya mengisytiharkan pembolehubah statik? Adakah itu akan menjadikan kelas tanpa nama menjadi kelas bersarang statik dan bukannya kelas dalam? Dalam erti kata lain, adakah ia akan kekurangan rujukan kepada kelas luar?"

"Tidak. Ia akan menjadi kelas dalaman tanpa nama. Lihat contoh ini."

Dengan kelas tanpa nama Tanpa kelas tanpa nama
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();
 }
}

"Saya faham. Hanya pembolehubah statik akan menjadi statik, bukan kelas."

"Ya."

"Malah, pengkompil mencipta kelas dalam untuk semua kelas dalam tanpa nama. Kelas ini biasanya dinamakan «1», «2», «3», dsb.