Kelas dalaman

S: Jadi apa yang baik untuk kelas dalaman?

J: Kelas dalaman bersarang dalam kelas lain. Kelas biasa adalah ahli langsung pakej, kelas atasan. Kelas dalaman, yang tersedia dengan Java 1.1, terdapat dalam empat rasa:

  • Kelas ahli statik
  • Kelas ahli
  • Kelas tempatan
  • Kelas tanpa nama

Mari kita lihat secara bergilir-gilir.

Secara ringkas, kelas ahli statik adalah ahli kelas yang statik. Seperti kaedah statik yang lain, kelas ahli statik mempunyai akses ke semua kaedah statik induk, atau kelas atasan, kelas.

Seperti kelas ahli statik, kelas ahli juga ditakrifkan sebagai ahli kelas. Tidak seperti variasi statik, kelas ahli adalah khusus dan mempunyai akses kepada semua kaedah dan ahli, bahkan thisrujukan ibu bapa .

Kelas tempatan dinyatakan dalam blok kod dan hanya dapat dilihat dalam blok itu, sama seperti pemboleh ubah kaedah lain.

Akhirnya, kelas tanpa nama adalah kelas tempatan yang tidak mempunyai nama.

Untuk menjawab soalan khusus anda, saya akan memberi tumpuan kepada kelas dalaman ahli dan tanpa nama kerana itulah kelas yang mungkin akan anda temui dan gunakan. Bagi saya, kelebihan kelas dalaman dapat dibahagikan kepada tiga kategori: kelebihan berorientasikan objek, kelebihan organisasi, dan kelebihan panggilan balik.

Kelebihan berorientasikan objek

Pada pendapat saya yang rendah hati, ciri terpenting dari kelas dalaman adalah bahawa ia membolehkan anda mengubah sesuatu menjadi objek yang biasanya tidak anda ubah menjadi objek. Itu membolehkan kod anda lebih berorientasikan objek daripada tanpa kelas dalaman.

Mari lihat kelas ahli. Oleh kerana contohnya adalah anggota contoh induknya, ia mempunyai akses kepada setiap anggota dan kaedah dalam induk. Pada pandangan pertama, ini mungkin tidak banyak; kita sudah mempunyai jenis akses dari kaedah dalam kelas induk. Walau bagaimanapun, kelas ahli membolehkan kami mengeluarkan logik daripada ibu bapa dan mengesahkannya. Sebagai contoh, kelas pokok mungkin mempunyai kaedah dan banyak kaedah penolong yang melakukan pencarian atau berjalan kaki di atas pokok. Dari sudut pandangan berorientasikan objek, pokok itu adalah pokok, bukan algoritma carian. Walau bagaimanapun, anda memerlukan pengetahuan mendalam mengenai struktur data pokok untuk menyelesaikan pencarian.

Kelas dalaman membolehkan kita membuang logik itu dan memasukkannya ke dalam kelasnya sendiri. Oleh itu, dari sudut pandang yang berorientasikan objek, kami telah menggunakan fungsi dari mana ia bukan miliknya dan memasukkannya ke dalam kelasnya sendiri. Melalui penggunaan kelas dalaman, kami berjaya melepaskan algoritma carian dari pokok. Sekarang, untuk mengubah algoritma carian, kita hanya boleh menukar kelas baru. Saya boleh teruskan, tetapi itu membuka kod kami untuk banyak kelebihan yang diberikan oleh teknik berorientasikan objek.

Kelebihan organisasi

Reka bentuk berorientasikan objek bukan milik semua orang, tetapi untungnya, kelas dalaman menyediakan lebih banyak. Dari sudut pandangan organisasi, kelas dalaman membolehkan kami mengatur struktur pakej kami dengan lebih banyak menggunakan ruang nama. Daripada membuang semuanya dalam pakej rata, kelas dapat lebih jauh bersarang di dalam kelas. Secara terang-terangan, tanpa kelas dalaman, kami terhad kepada struktur hierarki berikut:

pakej1 kelas 1 kelas 2 ... kelas n ... pakej n 

Dengan kelas dalaman kita boleh melakukan perkara berikut:

pakej 1 kelas 1 kelas 2 kelas 1 kelas 2 ... kelas n 

Digunakan dengan berhati-hati, kelas dalaman dapat memberikan hierarki struktur yang lebih sesuai dengan kelas anda.

Kelebihan panggilan balik

Kelas ahli dalaman dan kelas tanpa nama kedua-duanya menyediakan kaedah yang mudah untuk menentukan panggilan balik. Contoh yang paling jelas berkaitan dengan kod GUI. Walau bagaimanapun, penerapan panggilan balik boleh meluas ke banyak domain.

Sebilangan besar GUI Java mempunyai beberapa jenis komponen yang menghasut actionPerformed()panggilan kaedah. Malangnya, kebanyakan pembangun hanya mempunyai tetingkap utama mereka ActionListener. Hasilnya, semua komponen berkongsi actionPerformed()kaedah yang sama . Untuk mengetahui komponen mana yang melakukan tindakan tersebut, biasanya terdapat peralihan raksasa dan jelek dalam actionPerformed()metode ini.

Berikut adalah contoh pelaksanaan monolitik:

kelas awam SomeGUI meluaskan JFrame melaksanakan ActionListener {butang JButton dilindungi1; butang JButton dilindungi2; ... butang JButton dilindungiN; public void actionPerformed (ActionEvent e) {if (e.getSource () == button1) {// buat sesuatu} yang lain jika (e.getSource () == butang2) {... anda mendapat gambar

Setiap kali anda melihat suis atau besar if/ if elseblok, loceng penggera yang kuat akan mula berdering di fikiran anda. Secara umum, konstruksi seperti itu adalah reka bentuk berorientasikan objek yang buruk kerana perubahan dalam satu bahagian kod mungkin memerlukan perubahan yang sesuai dalam pernyataan suis. Kelas ahli dalaman dan kelas tanpa nama membolehkan kita menjauhi actionPerformed()kaedah beralih .

Sebagai gantinya, kita dapat menentukan kelas dalaman yang diterapkan ActionListeneruntuk setiap komponen yang ingin kita dengarkan. Itu boleh mengakibatkan banyak kelas dalaman. Walau bagaimanapun, kita dapat mengelakkan penyataan peralihan besar dan mendapat bonus tambahan merangkumi logika tindakan kita. Lebih-lebih lagi, pendekatan itu dapat meningkatkan prestasi. Dalam pertukaran di mana terdapat perbandingan n , kita dapat mengharapkan perbandingan n / 2 dalam kes rata-rata. Kelas dalaman membolehkan kita membuat korespondensi 1: 1 antara pelaku aksi dan pendengar tindakan. Dalam GUI yang besar, pengoptimuman semacam itu dapat memberi kesan yang besar terhadap prestasi. Pendekatan tanpa nama mungkin kelihatan seperti ini:

kelas awam SomeGUI memperluas JFrame {... pengisytiharan ahli butang ... dilindungi batal buildGUI () {button1 = JButton baru (); butang2 = JButton baru (); ... button1.addActionListener (java.awt.event.ActionListener baru () {public void actionPerformed (java.awt.event.ActionEvent e) {// buat sesuatu}}); .. ulangi untuk setiap butang

Menggunakan kelas ahli dalaman, program yang sama akan kelihatan seperti ini:

kelas awam SomeGUI memperluas JFrame {... pengisytiharan ahli butang // kelas definisi kelas dalaman Button1Handler melaksanakan ActionListener {public void actionPerformed (ActionEvent e) {// melakukan sesuatu}} ... tentukan kelas ahli dalaman untuk setiap butang dilindungi buildGUI () {// memulakan butang butang1 = JButton baru (); butang2 = JButton baru (); ... // daftar contoh pendengar tindakan kelas dalaman // untuk setiap butang butang1.addActionListener (Button1Handler baru ()); .. ulangi untuk setiap butang

Oleh kerana kelas dalam mempunyai akses ke semua perkara dalam ibu bapa, kita dapat memindahkan logik apa pun yang muncul dalam actionPerformed()pelaksanaan monolitik ke kelas dalaman.

Saya lebih suka menggunakan kelas ahli sebagai panggilan balik. Walau bagaimanapun, itu adalah masalah pilihan peribadi. Saya merasakan terlalu banyak kelas tanpa nama yang mengandungi kod. Saya juga merasakan bahawa kelas tanpa nama boleh menjadi tidak berat sebelah jika lebih besar daripada satu atau dua baris.

Kekurangan?

Seperti hal lain, anda harus mengambil yang baik dengan yang buruk. Kelas dalaman mempunyai kekurangannya. Dari sudut pemeliharaan, pemaju Java yang tidak berpengalaman mungkin sukar memahami kelas dalamannya. Penggunaan kelas dalam juga akan meningkatkan jumlah kelas dalam kod anda. Lebih-lebih lagi, dari sudut pandang pengembangan, kebanyakan alat Java sedikit kurang daripada sokongan mereka terhadap kelas dalam. Sebagai contoh, saya menggunakan VisualAge IBM untuk Java untuk pengekodan harian saya. Walaupun kelas dalaman akan disusun dalam VisualAge, tidak ada penyemak imbas atau templat kelas dalam. Sebaliknya, anda mesti menaip kelas dalaman secara langsung ke dalam definisi kelas. Itu menyukarkan melayari kelas dalam menjadi sukar. Ia juga sukar untuk menaip kerana anda kehilangan banyak VisualAge 'bantu menyelesaikan kod semasa anda menaip definisi kelas atau menggunakan kelas dalaman.

Tony Sintes adalah perunding kanan di ObjectWave, yang pakar dalam bidang telekomunikasi. Sintes, pengaturcara Java 1.1 yang disahkan oleh Sun dan pengembang Java 2, telah bekerja dengan Java sejak 1997.

Ketahui lebih lanjut mengenai topik ini

  • "Spesifikasi Kelas Dalaman," dari Sun, memberikan gambaran mendalam mengenai kelas dalaman

    //java.sun.com/products/jdk/1.1/docs/guide/innerclasses/spec/innerclasses.doc.html

Kisah ini, "Kelas dalaman" pada awalnya diterbitkan oleh JavaWorld.