Saya membaca pertanyaan ini dan berpikir bahwa itu akan dengan mudah diselesaikan (bukan karena itu tidak dapat dipecahkan tanpa) jika seseorang dapat menulis:
@Override
public String toString() {
return super.super.toString();
}
Saya tidak yakin apakah itu berguna dalam banyak kasus, tetapi saya bertanya - tanya mengapa itu tidak berguna dan jika sesuatu seperti ini ada dalam bahasa lain.
apa yang kalian pikirkan?
EDIT: Untuk memperjelas: ya saya tahu, itu tidak mungkin di Jawa dan saya tidak benar-benar melewatkannya. Ini bukan apa-apa yang saya harapkan untuk bekerja dan terkejut mendapatkan kesalahan kompiler. Saya hanya punya ide dan suka mendiskusikannya.
java
superclass
Tim Büthe
sumber
sumber
super.super.toString()
bertentangan dengan keputusan Anda sendiri ketika Anda memilih untuk memperpanjang kelas sehingga menerima semua (bukan sebagian) fitur-fiturnya.Jawaban:
Itu melanggar enkapsulasi. Anda seharusnya tidak dapat mem-bypass perilaku kelas induk. Masuk akal untuk kadang-kadang dapat mem-bypass perilaku kelas Anda sendiri (khususnya dari dalam metode yang sama) tetapi tidak dengan perilaku orang tua Anda. Sebagai contoh, misalkan kita memiliki basis "koleksi item", subkelas yang mewakili "koleksi item merah" dan subkelas yang mewakili "koleksi item merah besar". Masuk akal untuk memiliki:
Tidak apa-apa - RedItems selalu dapat yakin bahwa item yang dikandungnya semuanya berwarna merah. Sekarang anggaplah kita berada dapat memanggil super.super.add ():
Sekarang kita bisa menambahkan apa pun yang kita suka, dan invarian di
RedItems
rusak.Apakah itu masuk akal?
sumber
Saya pikir Jon Skeet memiliki jawaban yang benar. Saya hanya ingin menambahkan bahwa Anda dapat mengakses variabel gelap dari superclasses superclasses dengan melemparkan
this
:yang menghasilkan output:
(contoh dari JLS )
Namun, ini tidak berfungsi untuk pemanggilan metode karena pemanggilan metode ditentukan berdasarkan tipe runtime objek.
sumber
Saya pikir kode berikut memungkinkan untuk menggunakan super.super ... super.method () dalam banyak kasus. (Bahkan jika itu buruk untuk melakukannya)
Pendeknya
Penggunaan:
sumber
super.super.
mengundang programmer untuk menemukan cara-cara baru, berbelit-belit dan mengerikan untuk menembak diri sendiri dalam upaya mencari solusi, ini adalah contoh sempurna dari itu, karena rekan kerja Anda mungkin akan sangat membenci Anda karena menulis sesuatu seperti ini mereka akan menembak Anda secara pribadi dan secara harfiah di kaki. +1Saya tidak memiliki reputasi yang cukup untuk berkomentar sehingga saya akan menambahkan ini ke jawaban lain.
Jon Skeet menjawab dengan sangat baik, dengan contoh yang indah. Matt B ada benarnya: tidak semua superclasses memiliki supers. Kode Anda akan rusak jika Anda memanggil super dari super yang tidak memiliki super.
Pemrograman berorientasi objek (yang Java) adalah semua tentang objek, bukan fungsi. Jika Anda ingin pemrograman berorientasi tugas, pilih C ++ atau yang lainnya. Jika objek Anda tidak sesuai dengan kelas supernya, maka Anda perlu menambahkannya ke "kelas kakek-nenek", membuat kelas baru, atau menemukan super lain yang cocok dengannya.
Secara pribadi, saya menemukan keterbatasan ini sebagai salah satu kekuatan terbesar Jawa. Kode agak kaku dibandingkan dengan bahasa lain yang saya gunakan, tetapi saya selalu tahu apa yang diharapkan. Ini membantu dengan tujuan "sederhana dan akrab" Jawa. Dalam pikiran saya, memanggil super.super tidak sederhana atau akrab. Mungkin para pengembang merasakan hal yang sama?
sumber
Ada beberapa alasan bagus untuk melakukan ini. Anda mungkin memiliki subkelas yang memiliki metode yang diterapkan secara salah, tetapi metode induk diimplementasikan dengan benar. Karena itu milik perpustakaan pihak ketiga, Anda mungkin tidak dapat / tidak mau mengubah sumbernya. Dalam hal ini, Anda ingin membuat subkelas tetapi mengganti satu metode untuk memanggil metode super.super.
Seperti yang ditunjukkan oleh beberapa poster lain, dimungkinkan untuk melakukan ini melalui refleksi, tetapi harus mungkin untuk melakukan sesuatu seperti
(SuperSuperClass ini) .theMethod ();
Saya sedang menangani masalah ini sekarang - perbaikan cepatnya adalah dengan menyalin dan menempelkan metode superclass ke dalam metode sub-kelas :)
sumber
Selain poin yang sangat baik yang telah dibuat orang lain, saya pikir ada alasan lain: bagaimana jika superclass tidak memiliki superclass?
Karena setiap kelas secara alami meluas (setidaknya)
Object
,super.whatever()
akan selalu merujuk pada metode dalam superclass. Tetapi bagaimana jika kelas Anda hanya meluasObject
- apa yang akansuper.super
dirujuk kemudian? Bagaimana seharusnya perilaku itu ditangani - kesalahan kompiler, NullPointer, dll?Saya pikir alasan utama mengapa ini tidak diperbolehkan adalah karena melanggar enkapsulasi, tetapi ini mungkin juga merupakan alasan kecil.
sumber
Saya pikir jika Anda menimpa metode dan ingin semua versi super-kelas itu (seperti, katakan untuk
equals
), maka Anda hampir selalu ingin memanggil versi superclass langsung terlebih dahulu, yang mana akan memanggil versi superclass pada gilirannya jika ia menginginkannya. .Saya pikir itu jarang masuk akal (jika sama sekali. Saya tidak bisa memikirkan kasus di mana ia melakukannya) untuk memanggil versi superclass sewenang-wenang dari suatu metode. Saya tidak tahu apakah itu mungkin sama sekali di Jawa. Itu bisa dilakukan di C ++:
sumber
Di tebak, karena tidak sering digunakan. Satu-satunya alasan saya bisa melihatnya menggunakannya adalah jika orang tua langsung Anda telah menimpa beberapa fungsi dan Anda mencoba mengembalikannya kembali ke aslinya.
Yang menurut saya bertentangan dengan prinsip-prinsip OO, karena orang tua langsung kelas harus lebih dekat dengan kelas Anda daripada kakek-nenek.
sumber
Lihatlah ini proyek Github, terutama variabel objectHandle. Proyek ini menunjukkan bagaimana memanggil metode kakek-nenek secara aktual dan akurat.
Untuk berjaga-jaga jika tautannya rusak, berikut adalah kodenya:
Selamat Coding !!!!
sumber
Saya akan meletakkan tubuh metode super.super di metode lain, jika mungkin
Atau jika Anda tidak dapat mengubah kelas super-super, Anda dapat mencoba ini:
Dalam kedua kasus tersebut,
hasil untuk "Saya super super"
sumber
Tampaknya akan mungkin untuk setidaknya mendapatkan kelas dari superclass superclass, meskipun tidak harus contoh itu, menggunakan refleksi; jika ini mungkin berguna, silakan pertimbangkan Javadoc di http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#getSuperclass ()
sumber
run: A BUILD SUCCESSFUL (total waktu: 0 detik)
sumber
Memanggil super.super.method () masuk akal ketika Anda tidak dapat mengubah kode kelas dasar. Ini sering terjadi ketika Anda memperluas perpustakaan yang ada.
Tanyakan kepada diri Anda terlebih dahulu, mengapa Anda memperluas kelas itu? Jika jawabannya "karena saya tidak bisa mengubahnya" maka Anda dapat membuat paket dan kelas yang tepat di aplikasi Anda, dan menulis ulang metode nakal atau membuat delegasi:
Misalnya, Anda dapat membuat kelas org.springframework.test.context.junit4.SpringJUnit4ClassRunner di aplikasi Anda sehingga kelas ini harus dimuat sebelum yang asli dari toples. Kemudian tulis ulang metode atau konstruktor.
Perhatian: Ini adalah retasan absolut, dan sangat TIDAK disarankan untuk digunakan tetapi BEKERJA! Penggunaan pendekatan ini berbahaya karena kemungkinan masalah dengan pemuat kelas. Ini juga dapat menyebabkan masalah setiap kali Anda akan memperbarui perpustakaan yang berisi kelas yang ditimpa.
sumber
Saya memiliki situasi seperti ini ketika arsitekturnya membangun fungsionalitas umum dalam CustomBaseClass umum yang mengimplementasikan atas nama beberapa kelas turunan. Namun, kita perlu mengelak dari logika umum untuk metode khusus untuk kelas turunan tertentu. Dalam kasus seperti itu, kita harus menggunakan implementasi super.super.methodX.
Kami mencapai ini dengan memperkenalkan anggota boolean di CustomBaseClass, yang dapat digunakan untuk secara selektif menunda implementasi kustom dan menghasilkan implementasi kerangka kerja default jika diinginkan.
Namun, dengan prinsip arsitektur yang baik diikuti dalam kerangka kerja serta aplikasi, kita dapat menghindari situasi seperti itu dengan mudah, dengan menggunakan pendekatan hasA, bukan pendekatan isA. Tetapi setiap saat itu tidak terlalu praktis untuk mengharapkan arsitektur yang dirancang dengan baik di tempat, dan karenanya perlu untuk menjauh dari prinsip-prinsip desain yang solid dan memperkenalkan hacks seperti ini. Hanya 2 sen saya ...
sumber
@ Jon Skeet Penjelasan yang bagus. IMO jika seseorang ingin memanggil metode super.super maka seseorang harus ingin mengabaikan perilaku orangtua langsung, tetapi ingin mengakses perilaku grand parent. Ini dapat dicapai melalui contoh Dari. Seperti kode di bawah ini
Ini kelas pengemudi,
Output dari ini akan menjadi
Perilaku printClass kelas B akan diabaikan dalam kasus ini. Saya tidak yakin apakah ini praktik yang ideal atau bagus untuk mencapai super.super, tetapi masih berfungsi.
sumber
Jika Anda pikir Anda akan membutuhkan superclass, Anda bisa mereferensikannya dalam variabel untuk kelas itu. Sebagai contoh:
Harus mencetak:
sumber
new UltraFoo.getNumber()
tidak mau mengkompilasi, karena kamu merindukan tanda kurung di sana. Namun, saya baru saja menghapus donvote saya, karena konsep kode Anda cukup jelas sekarang, terima kasih!IMO, ini cara bersih untuk mencapai
super.super.sayYourName()
perilaku di Jawa.Keluaran:
Request to lie: d.sayYourName(true) returns Grandma Fedora
Request not to lie: d.sayYourName(false) returns Little girl Masha
sumber
Saya pikir ini adalah masalah yang melanggar perjanjian warisan.
Dengan memperluas kelas Anda mematuhi / menyetujui perilakunya, fitur
Sementara saat menelepon
super.super.method()
, Anda ingin melanggar perjanjian kepatuhan Anda sendiri.Anda tidak bisa memilih cherry dari kelas super .
Namun, mungkin ada situasi ketika Anda merasa perlu menelepon
super.super.method()
- biasanya tanda desain yang buruk, dalam kode Anda atau dalam kode yang Anda warisi!Jika kelas super dan super super tidak dapat di-refactored (beberapa kode lawas), maka pilihlah komposisi daripada warisan.
Pemecahan enkapsulasi adalah ketika Anda @Override beberapa metode dengan memecah kode enkapsulasi. Metode yang dirancang untuk tidak diganti akan ditandai final .
sumber
Dalam C # Anda dapat memanggil metode leluhur seperti ini:
Anda juga dapat melakukan ini di Delphi:
Tetapi di Jawa Anda dapat melakukan fokus seperti itu hanya dengan beberapa peralatan. Salah satu cara yang mungkin adalah:
output hasil objC.DoIt ():
sumber
Ini mudah dilakukan. Contohnya:
C subclass dari B dan B subclass dari A. Keduanya memiliki metode methodName () misalnya.
Jalankan kelas C Output akan menjadi: Kelas A Kelas C
Alih-alih output: Kelas A Kelas B Kelas C
sumber
Output: Dicetak di GrandDad
sumber
super.super.method()
kode tidak valid di Jawa.Kata kunci super hanyalah cara untuk memanggil metode dalam superclass. Dalam tutorial Java: https://docs.oracle.com/javase/tutorial/java/IandI/super.html
Jika metode Anda menimpa salah satu metode superclass-nya, Anda dapat memanggil metode yang ditimpa melalui penggunaan kata kunci super.
Jangan percaya bahwa itu adalah referensi dari objek super !!! Tidak, itu hanya kata kunci untuk memanggil metode dalam superclass.
Berikut ini sebuah contoh:
Saat Anda menelepon
cat.doSth()
, metodedoSth()
di kelasAnimal
akan dicetakthis
dan itu adalah kucing.sumber