Java tidak mengizinkan banyak pewarisan, tetapi memungkinkan implementasi beberapa antarmuka. Mengapa?
153
Java tidak mengizinkan banyak pewarisan, tetapi memungkinkan implementasi beberapa antarmuka. Mengapa?
Jawaban:
Karena antarmuka hanya menentukan apa yang dikerjakan kelas, bukan bagaimana melakukannya.
Masalah dengan multiple inheritance adalah bahwa dua kelas dapat mendefinisikan cara berbeda untuk melakukan hal yang sama, dan subclass tidak dapat memilih mana yang akan dipilih.
sumber
Salah satu instruktur perguruan tinggi saya menjelaskan kepada saya seperti ini:
Jadi salah satu masalah utama adalah jika Anda memiliki dua kelas induk, mereka mungkin memiliki implementasi yang berbeda dari fitur yang sama - atau mungkin dua fitur berbeda dengan nama yang sama, seperti dalam contoh instruktur saya. Maka Anda harus berurusan dengan memutuskan mana subclass Anda akan digunakan. Ada beberapa cara untuk menangani hal ini, tentu saja - C ++ melakukannya - tetapi para perancang Jawa merasa bahwa ini akan membuat segalanya menjadi terlalu rumit.
Dengan antarmuka, Anda menggambarkan sesuatu yang mampu dilakukan oleh kelas, daripada meminjam metode kelas lain untuk melakukan sesuatu. Beberapa antarmuka jauh lebih kecil kemungkinannya menyebabkan konflik rumit yang perlu diselesaikan daripada beberapa kelas induk.
sumber
Karena warisan terlalu sering digunakan bahkan ketika Anda tidak bisa mengatakan "hei, metode itu terlihat berguna, saya akan memperpanjang kelas itu juga".
sumber
Jawaban dari pertanyaan ini terletak pada kerja internal kompiler java (konstruktor chaining). Jika kita melihat kerja internal kompiler java:
Setelah mengkompilasi ini terlihat seperti:
ketika kita memperluas kelas dan membuat objeknya, satu rantai konstruktor akan berjalan hingga
Object
kelas.Kode di atas akan berjalan dengan baik. tetapi jika kita memiliki kelas lain yang disebut
Car
memanjangBank
dan satu kelas hybrid (multiple inheritance) disebutSBICar
:Dalam hal ini (SBICar) akan gagal membuat rantai konstruktor ( kompilasi ambiguitas waktu ).
Untuk antarmuka ini diizinkan karena kami tidak dapat membuat objek darinya.
Untuk konsep
default
danstatic
metode baru silakan merujuk default di antarmuka .Semoga ini akan menyelesaikan pertanyaan Anda. Terima kasih.
sumber
Menerapkan banyak antarmuka sangat berguna dan tidak menyebabkan banyak masalah bagi pelaksana bahasa maupun programmer. Jadi itu diizinkan. Berbagai warisan sementara juga bermanfaat, dapat menyebabkan masalah serius bagi pengguna ( berlian kematian yang ditakuti ). Dan sebagian besar hal yang Anda lakukan dengan pewarisan berganda juga dapat dilakukan dengan komposisi atau menggunakan kelas batin. Jadi multiple inheritance dilarang membawa lebih banyak masalah daripada keuntungan.
sumber
ToyotaCar
danHybridCar
keduanya berasal dariCar
dan mengesampingkanCar.Drive
, dan jikaPriusCar
mewarisi keduanya tetapi tidak mengesampingkanDrive
, sistem tidak akan memiliki cara untuk mengidentifikasi apa yangCar.Drive
harus dilakukan virtual . Antarmuka menghindari masalah ini dengan menghindari kondisi miring di atas.void UseCar(Car &foo)
; tidak dapat diharapkan untuk memasukkan disambiguasi antaraToyotaCar::Drive
danHybridCar::Drive
(karena seharusnya sering tidak mengetahui atau peduli bahwa jenis-jenis lain bahkan ada ) Suatu bahasa dapat, seperti halnya C ++, memerlukan kode yangToyotaCar &myCar
ingin meneruskannyaUseCar
terlebih dahulu harus dilemparkan ke salah satuHybridCar
atauToyotaCar
, tetapi karena ((Mobil) (HybridCar) myCar) .Drive` dan((Car)(ToyotaCar)myCar).Drive
akan melakukan hal yang berbeda, yang akan menyiratkan bahwa upcasts tidak melestarikan identitas.Anda dapat menemukan jawaban yang akurat untuk kueri ini di halaman dokumentasi oracle tentang multiple inheritance
Multiple inheritance of state: Kemampuan untuk mewarisi bidang dari beberapa kelas
Jika beberapa pewarisan diizinkan dan Saat Anda membuat objek dengan membuat instance kelas itu, objek itu akan mewarisi bidang dari semua superclasses kelas. Itu akan menyebabkan dua masalah.
Berbagai warisan implementasi: Kemampuan untuk mewarisi definisi metode dari beberapa kelas
Masalah dengan pendekatan ini: konflik nama dan ambiguitas . Jika subkelas dan superclass berisi nama metode (dan tanda tangan) yang sama, kompiler tidak dapat menentukan versi yang akan dipanggil.
Tetapi java mendukung tipe multiple inheritance ini dengan metode default , yang telah diperkenalkan sejak rilis Java 8. Kompiler Java menyediakan beberapa aturan untuk menentukan metode default mana yang digunakan kelas tertentu.
Lihat posting SE di bawah ini untuk detail lebih lanjut tentang menyelesaikan masalah berlian:
Apa perbedaan antara kelas abstrak dan antarmuka di Java 8?
Multiple inheritance of type: Kemampuan suatu kelas untuk mengimplementasikan lebih dari satu antarmuka.
Karena antarmuka tidak mengandung bidang yang dapat diubah, Anda tidak perlu khawatir tentang masalah yang timbul dari banyak pewarisan status di sini.
sumber
Dikatakan bahwa objek state disebut sehubungan dengan bidang di dalamnya dan itu akan menjadi ambigu jika terlalu banyak kelas diwarisi. Ini tautannya
http://docs.oracle.com/javase/tutorial/java/IandI/multipleinheritance.html
sumber
Java mendukung banyak pewarisan melalui antarmuka saja. Kelas dapat mengimplementasikan sejumlah antarmuka tetapi hanya dapat memperluas satu kelas.
Warisan berganda tidak didukung karena menyebabkan masalah berlian yang mematikan. Namun, ini dapat diselesaikan tetapi mengarah ke sistem yang kompleks sehingga banyak warisan telah dijatuhkan oleh para pendiri Java.
Dalam sebuah buku putih berjudul “Java: an Overview” oleh James Gosling pada Februari 1995 ( tautan ) memberikan gambaran mengapa banyak warisan tidak didukung di Jawa.
Menurut Gosling:
sumber
Untuk alasan yang sama C # tidak memungkinkan pewarisan berganda tetapi memungkinkan Anda untuk mengimplementasikan beberapa antarmuka.
Pelajaran yang dapat dipetik dari C ++ w / multiple inheritence adalah bahwa hal itu menyebabkan lebih banyak masalah daripada nilainya.
Antarmuka adalah kontrak hal-hal yang harus diimplementasikan oleh kelas Anda. Anda tidak mendapatkan fungsionalitas apa pun dari antarmuka. Inheritence memungkinkan Anda untuk mewarisi fungsi kelas induk (dan dalam multiple-inheritence, itu bisa sangat membingungkan).
Mengizinkan banyak antarmuka memungkinkan Anda untuk menggunakan Pola Desain (seperti Adaptor) untuk memecahkan jenis masalah yang sama yang dapat Anda pecahkan dengan menggunakan pewarisan berganda, tetapi dengan cara yang jauh lebih andal dan dapat diprediksi.
sumber
D1
danD2
keduanya mewarisi dariB
, dan masing-masing menimpa fungsif
, dan jikaobj
adalah sebuah instance dari tipeS
yang mewarisi dari keduanyaD1
danD2
tetapi tidak menimpaf
, maka casting referensiS
keD1
harus menghasilkan sesuatu yangf
menggunakanD1
override, dan casting untukB
tidak boleh ganti itu. Demikian juga pengecoran referensiS
untukD2
harus menghasilkan sesuatu yangf
menggunakan yangD2
menimpa, dan casting untukB
tidak harus mengubah itu. Jika suatu bahasa tidak perlu memperbolehkan anggota virtual untuk ditambahkan ...Karena topik ini tidak dekat, saya akan memposting jawaban ini, saya harap ini membantu seseorang untuk memahami mengapa java tidak memungkinkan banyak pewarisan.
Pertimbangkan kelas berikut:
Dalam hal ini kelas Abc tidak memperluas apa-apa, bukan? Tidak begitu cepat, kelas ini secara implisit memperluas Object kelas, kelas dasar yang memungkinkan semuanya berfungsi di java. Semuanya adalah objek.
Jika Anda mencoba untuk menggunakan kelas atas Anda akan melihat bahwa IDE Anda memungkinkan Anda untuk menggunakan metode seperti:
equals(Object o)
,toString()
, dll, tetapi Anda tidak menyatakan metode tersebut, mereka datang dari kelas dasarObject
Kamu bisa mencoba:
Ini baik-baik saja, karena kelas Anda tidak akan implisit meluas
Object
tetapi akan meluasString
karena Anda mengatakannya. Pertimbangkan perubahan berikut:Sekarang kelas Anda akan selalu mengembalikan "halo" jika Anda memanggil toString ().
Sekarang bayangkan kelas berikut:
Sekali lagi kelas
Flyer
implisit extends Object yang memiliki metodetoString()
, setiap kelas akan memiliki metode ini karena mereka semua diperluasObject
secara tidak langsung, jadi, jika Anda menelepontoString()
dariBird
,toString()
java mana yang harus digunakan? DariAbc
atauFlyer
? Ini akan terjadi dengan setiap kelas yang mencoba memperluas dua atau lebih kelas, untuk menghindari "metode tabrakan" semacam ini mereka membangun ide antarmuka , pada dasarnya Anda bisa menganggapnya sebagai kelas abstrak yang tidak memperluas Obyek secara tidak langsung . Karena mereka abstrak, mereka harus diimplementasikan oleh sebuah kelas, yang merupakan objek(Anda tidak dapat membuat antarmuka saja, mereka harus diimplementasikan oleh sebuah kelas), sehingga semuanya akan terus berfungsi dengan baik.Untuk membedakan kelas dari antarmuka, penerapan kata kunci hanya diperuntukkan bagi antarmuka.
Anda bisa mengimplementasikan antarmuka apa pun yang Anda suka di kelas yang sama karena mereka tidak memperluas apa pun secara default (tapi Anda bisa membuat antarmuka yang memperluas antarmuka lain, tetapi sekali lagi, antarmuka "ayah" tidak akan memperluas Obyek "), sehingga antarmuka adalah hanya sebuah antarmuka dan mereka tidak akan menderita dari " metode tanda tangan colissions ", jika mereka melakukan compiler akan memberikan peringatan kepada Anda dan Anda hanya perlu mengubah metode tanda tangan untuk memperbaikinya (signature = nama metode + params + jenis kembali) .
sumber
Karena sebuah antarmuka hanyalah kontrak. Dan kelas sebenarnya adalah wadah untuk data.
sumber
Misalnya dua kelas A, B memiliki metode yang sama m1 (). Dan kelas C memperpanjang A, B.
Sekarang, kelas C akan mencari definisi m1. Pertama, ia akan mencari di kelas jika tidak menemukan maka akan memeriksa ke kelas orang tua. Kedua A, B memiliki definisi Jadi di sini terjadi ambiguitas definisi mana yang harus dipilih. Jadi JAWA TIDAK MENDUKUNG WARISAN GANDA.
sumber
Java tidak mendukung multiple inheritance karena dua alasan:
Object
kelas. Ketika mewarisi dari lebih dari satu kelas super, sub kelas mendapatkan ambiguitas untuk mendapatkan properti dari kelas Obyek.super()
untuk memanggil konstruktor kelas perjamuan. Jika kelas memiliki lebih dari satu kelas super, itu jadi bingung.Jadi, ketika satu kelas memanjang dari lebih dari satu kelas super, kami mendapatkan kesalahan waktu kompilasi.
sumber
Ambil contoh kasus di mana Kelas A memiliki metode getSomething dan kelas B memiliki metode getSomething dan kelas C meluas A dan B. Apa yang akan terjadi jika seseorang bernama C.getSomething? Tidak ada cara untuk menentukan metode mana yang harus dihubungi.
Antarmuka pada dasarnya hanya menentukan metode apa yang perlu dimiliki oleh kelas pelaksana. Kelas yang mengimplementasikan beberapa antarmuka hanya berarti kelas harus mengimplementasikan metode dari semua antarmuka itu. Whci tidak akan menyebabkan masalah apa pun seperti yang dijelaskan di atas.
sumber
Pertimbangkan skenario di mana Test1, Test2 dan Test3 adalah tiga kelas. Kelas Test3 mewarisi kelas Test2 dan Test1. Jika kelas Test1 dan Test2 memiliki metode yang sama dan Anda memanggilnya dari objek kelas anak, akan ada ambiguitas untuk memanggil metode dari kelas Test1 atau Test2 tetapi tidak ada ambiguitas untuk antarmuka seperti di antarmuka tidak ada implementasi di sana.
sumber
Java tidak mendukung multiple inheritance, multipath dan hybrid inheritance karena masalah ambiguitas:
pewarisan berganda
sumber
secara sederhana kita semua tahu, kita dapat mewarisi (memperluas) satu kelas tetapi kita dapat mengimplementasikan begitu banyak antarmuka .. itu karena dalam antarmuka kita tidak memberikan implementasi, katakan saja fungsionalitasnya. misalkan jika java dapat meluas begitu banyak kelas dan mereka memiliki metode yang sama .. pada titik ini jika kita mencoba memanggil metode super kelas di sub kelas metode apa yang seharusnya dijalankan ??, kompiler menjadi bingung contoh: - mencoba beberapa ekstensi tetapi dalam antarmuka metode-metode itu tidak memiliki tubuh kita harus mengimplementasikannya di sub kelas .. coba beberapa alat jadi jangan khawatir ..
sumber
* Ini adalah jawaban sederhana karena saya seorang pemula di Jawa *
Anggap ada tiga kelas
X
,Y
danZ
.Jadi kita mewarisi seperti
X extends Y, Z
Dan keduanyaY
danZ
memiliki metodealphabet()
dengan tipe pengembalian dan argumen yang sama. Metode inialphabet()
diY
mengatakan untuk menampilkan alfabet pertama dan alfabet metode diZ
mengatakan menampilkan alfabet terakhir . Jadi inilah ambiguitas ketikaalphabet()
dipanggil olehX
. Apakah itu mengatakan untuk menampilkan alfabet pertama atau terakhir ??? Jadi java tidak mendukung multiple inheritance. Dalam hal Antarmuka, pertimbangkanY
dan . Jadi tidak ada alasan untuk meningkatkan ambiguitas. Kita dapat mendefinisikan metode dengan apa pun yang kita inginkan di dalam kelas .Z
sebagai antarmuka. Jadi keduanya akan berisi deklarasi metodealphabet()
tetapi bukan definisi. Itu tidak akan memberitahu apakah akan menampilkan alfabet pertama atau alfabet terakhir atau apa pun tetapi hanya akan mendeklarasikan metodealphabet()
X
Jadi singkatnya, dalam definisi Interface dilakukan setelah implementasi sehingga tidak ada kebingungan.
sumber