Kelas dalam anonim, dan contoh - 1

"Hai, Amigo!"

"Tapi kita sudah menyapa, Ellie!"

"Hei, jangan berdebat dengan bibimu. Di abad ke-31, jika kamu tidak bertemu seseorang selama lebih dari setengah jam, sudah menjadi kebiasaan untuk menyapa lagi. Jadi jangan beri aku sikapmu!"

"Ngomong-ngomong, saatnya untuk topik menarik lainnya: reproduksi robot!"

"O_O."

"Hanya bercanda, topik barunya adalah kelas batin anonim ."

"Di Java, terkadang ada situasi di mana Anda memerlukan kelas untuk mewarisi beberapa kelas. Karena Java tidak mendukung pewarisan berganda, mereka telah memecahkan masalah ini menggunakan kelas dalam: di kelas kami, kami mendeklarasikan kelas dalam dan membuat itu mewarisi kelas apa pun yang kita butuhkan untuk mewarisi. Berikut ini contohnya:"

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 membutuhkan subkelas dari kelas Thread untuk mengganti metode run-nya."

"Itulah mengapa di kelas Tiger kami mendeklarasikan kelas dalam TigerThread , yang mewarisi Thread dan menggantikan metode run.

"Untuk kenyamanan, kami mendefinisikan dua metode di kelas Tiger: tigerRun dan startTiger (yang serupa dengan metode run dan start Thread."

"Dalam metode tigerStart, kami membuat objek TigerThread dan memanggil metode start()."

"JVM akan membuat utas baru yang akan mulai berjalan saat metode run TigerThread dipanggil."

"Metode ini kemudian memanggil metode run kami : tigerRun ."

"Saya telah bekerja dengan utas sebelumnya, jadi ini tampak mudah."

"Apakah kita harus memberi nama metode tigerRun dan tigerStart?"

"Tidak, kita bisa menyebut mereka lari dan mulai, tetapi saya juga ingin menunjukkan bahwa kita tidak mewarisi Thread. Penjelasan mungkin lebih membingungkan."

"OK. Kalau begitu saya pikir saya mengerti. Tetapi jika tigerStart dipanggil untuk kedua kalinya, kita akan membuat dan memulai objek Thread kedua. Bukankah itu berarti kita akan memiliki «satu harimau berjalan di dua utas yang berbeda»? "

"Yah, bukankah kamu tajam! Kamu benar, dan itu tidak baik. Mari kita tulis ulang kodenya seperti ini:"

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

"Itu tidak terlalu sempurna. Kamu masih tidak bisa memanggil metode seperti itu dua kali. Tapi kali ini, setidaknya kita tidak akan membuat utas kedua dan membuatnya tampak seperti semuanya baik-baik saja."

"Betul. Kedua kalinya Tiger dimulai, kamu akan mendapat pengecualian."

"Aku sudah menemukan kesalahan lebih baik darimu, Ellie!"

"Ya, kamu baik-baik saja. Kalau begitu mari kita beralih ke kelas batin anonim."

"Perhatikan beberapa aspek kode di atas:"

1) Kami mewarisi kelas Thread, tetapi praktis tidak menerapkan kode di sana. "Itu lebih dari «kami harus mewarisi kelas Thread» daripada «kami mewarisinya untuk memperluasnya».

2) Hanya satu objek TigerThread yang akan dibuat.

Dengan kata lain, kami menulis banyak kode hanya untuk mengganti satu metode dan membuat satu objek.

Apakah Anda ingat bagaimana saya berbicara tentang penemuan konstruktor?

Sebelum konstruktor Setelah konstruktor
TigerThread thread = new TigerThread();

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

"Saya melihat kodenya menjadi lebih ringkas, tetapi saya tidak begitu mengerti apa yang terjadi."

"Kita bisa menggabungkan empat hal menjadi satu:"

1) deklarasi kelas turunan

2) metode menimpa

3) deklarasi variabel

4) pembuatan instance dari kelas turunan.

"Faktanya, yang kami lakukan adalah menggabungkan dua operasi: mendeklarasikan kelas turunan dan membuat turunan dari kelas tersebut."

Tanpa kelas anonim Dengan kelas anonim
Cat tiger = new Tiger();

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

"Mari jelajahi sintaks lagi:"

Deklarasi variabel Thread
Thread thread = new Thread();
Deklarasi variabel yang tipenya adalah «kelas anonim yang mewarisi Thread»
Thread thread = new Thread()
{

};

"Perhatikan bahwa kita tidak hanya mendefinisikan kelas baru. Kita membuat variabel—ada titik koma di akhir!"

"Dan jika kita ingin mengganti metode run, maka kita perlu menulis ini:"

Deklarasi variabel Thread
Thread thread = new Thread()
{
 public void run()
  {
   System.out.println("new run-method");
  }
};

"Kamu mengerti dengan cepat. Kerja bagus!"

"Terima kasih. Bagaimana jika kita memerlukan metode lain yang bukan bagian dari kelas Thread?"

"Kamu bisa menulisnya."

"Meskipun anonim, ini adalah kelas dalam yang lengkap:"

kode jawa Keterangan
Thread thread = new Thread()
{
  public void run()
  {
   printHi();
  }

  public void printHi()
  {
   System.out.println("Hi!");
  }
};
Merah: kode untuk membuat variabel.

Hijau: kode untuk membuat objek.

Biru: kode untuk kelas turunan anonim.

"Kelas batin penuh?"

"Jadi saya bisa menggunakan variabel kelas luar?"

"Sangat."

"Dan saya bisa meneruskan sesuatu ke konstruktor?"

"Ya, tapi hanya argumen untuk konstruktor superclass:"

Kelas Contoh kelas dalam anonim
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);
  }
};

"Kita tidak bisa menambahkan parameter kita sendiri ke konstruktor orang lain. Tapi kita bisa menggunakan variabel kelas luar, yang mengkompensasi kekurangan ini dengan baik."

"Bagaimana jika saya masih benar-benar perlu menambahkan parameter lain ke konstruktor?"

"Kemudian nyatakan inner class biasa (non-anonim) dan gunakan itu."

"Benar, aku hampir lupa tentang itu."

"Bagaimana jika saya mendeklarasikan variabel statis? Apakah itu akan membuat kelas anonim menjadi kelas bersarang statis daripada kelas dalam? Dengan kata lain, apakah itu akan kekurangan referensi ke kelas luar?"

"Tidak. Itu akan menjadi kelas dalam yang anonim. Lihat contoh-contoh ini."

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

"Begitu. Hanya variabel statis yang statis, bukan kelasnya."

"Ya."

"Faktanya, kompiler membuat kelas dalam untuk semua kelas dalam anonim. Kelas-kelas ini biasanya diberi nama «1», «2», «3», dll."