Dalam salah satu wawancara saya, saya ditanya "Jika kita bisa membuat kelas abstrak?"
Jawaban saya adalah "Tidak, kami tidak bisa". Tetapi, pewawancara mengatakan kepada saya, "Kita bisa salah."
Saya sedikit berdebat tentang ini. Kemudian dia mengatakan kepada saya untuk mencobanya sendiri di rumah.
abstract class my {
public void mymethod() {
System.out.print("Abstract");
}
}
class poly {
public static void main(String a[]) {
my m = new my() {};
m.mymethod();
}
}
Di sini, saya membuat instance dari kelas saya dan memanggil metode kelas abstrak. Adakah yang bisa menjelaskan ini padaku? Apakah saya benar-benar salah selama wawancara?
B
dari satu abstrakA
, selama bagian konstruksi dariB
contoh, yang terdiri menjalankanA
's konstruktor, objek jenis runtime sebenarnyaA
. Namun hanya sementara.Jawaban:
Tidak, Anda tidak membuat instance dari kelas abstrak Anda di sini. Alih-alih, Anda membuat instance dari subclass anonim dari kelas abstrak Anda. Dan kemudian Anda memohon metode pada Anda referensi kelas abstrak menunjuk ke objek subclass .
Perilaku ini jelas tercantum dalam JLS - Bagian # 15.9.1 : -
Tekankan milikku.
Juga, di JLS - Bagian # 12.5 , Anda dapat membaca tentang Proses Pembuatan Objek . Saya akan mengutip satu pernyataan dari itu di sini: -
Anda dapat membaca tentang prosedur lengkap pada tautan yang saya berikan.
Untuk secara praktis melihat bahwa kelas yang dipakai adalah SubClass Anonim , Anda hanya perlu mengkompilasi kedua kelas Anda. Misalkan Anda meletakkan kelas-kelas itu dalam dua file yang berbeda:
My.java:
Poly.java:
Sekarang, kompilasi kedua file sumber Anda:
Sekarang di direktori tempat Anda menyusun kode sumber, Anda akan melihat file kelas berikut:
Lihat kelas itu -
Poly$1.class
. Ini adalah file kelas yang dibuat oleh kompiler yang sesuai dengan subkelas anonim yang Anda instantiated menggunakan kode di bawah ini:Jadi, jelas bahwa ada kelas yang berbeda sedang dipakai. Hanya saja, kelas itu diberi nama hanya setelah kompilasi oleh kompiler.
Secara umum, semua subclass anonim di kelas Anda akan dinamai dengan cara ini:
Angka-angka itu menunjukkan urutan di mana kelas-kelas anonim muncul di kelas terlampir.
sumber
instance of
daninstantiating
. Anda hanya instantiate satu kelas, sedangkan objek yang Anda buat bisa menjadi instance dari beberapa kelas karena pewarisan.Di atas instantiates kelas batin anonim yang merupakan subkelas dari
my
kelas abstrak. Ini tidak sepenuhnya setara dengan instantiate kelas abstrak itu sendiri. OTOH, setiap turunan subclass adalah turunan dari semua kelas dan antarmuka supernya, sehingga sebagian besar kelas abstrak memang instantiated dengan membuat instance salah satu dari subkelas konkret mereka.Jika pewawancara hanya mengatakan "salah!" tanpa menjelaskan, dan memberikan contoh ini, sebagai contoh tandingan yang unik, saya pikir dia tidak tahu apa yang dia bicarakan.
sumber
subclassInstance instanceof SuperClass
akan mengembalikan true, jadi objeknya adalah instance dari superclass, yang berarti superclass telah di-instanciated. Tapi itu hanya tipuan semantik.= my() {};
berarti bahwa ada implementasi anonim, tidak Instansiasi sederhana dari suatu obyek, yang seharusnya:= my()
. Anda tidak pernah dapat membuat instance kelas abstrak.sumber
Hanya pengamatan yang bisa Anda lakukan:
poly
meluasmy
? Ini tidak berguna ...my.class
,poly.class
danpoly$1.class
Bisakah kita instantiate kelas abstrak?
Tidak, kami tidak bisa. Yang bisa kita lakukan adalah, membuat kelas anonim (itu file ketiga) dan instantiate.
Bagaimana dengan instantiasi kelas super?
Kelas super abstrak tidak dipakai oleh kami tetapi oleh java.
EDIT: Minta dia untuk menguji ini
output adalah:
sumber
Serializable s = new Serializable() {};
(yang cukup berguna) dan jika ditandai ke kode Anda akan memberikanclass my$3
(atau apa pun melampirkan kelas dan nomor)Anda dapat menjawab, hanya dalam satu baris
Tapi, pewawancara masih belum setuju, maka Anda bisa memberitahunya
Dan, menurut kelas Anonim, kelas dideklarasikan dan instantiate di tempat / baris yang sama
Jadi, mungkin saja pewawancara tertarik untuk memeriksa tingkat kepercayaan Anda dan seberapa banyak yang Anda ketahui tentang OOP.
sumber
Bagian teknis telah tercakup dengan baik dalam jawaban lainnya, dan sebagian besar berakhir dengan:
"Dia salah, dia tidak tahu apa-apa, minta dia untuk bergabung dengan SO dan menyelesaikan semuanya :)"
Saya ingin membahas fakta (yang telah disebutkan dalam jawaban lain) bahwa ini mungkin menjadi pertanyaan yang menegangkan dan merupakan alat penting bagi banyak pewawancara untuk mengetahui lebih banyak tentang Anda dan bagaimana Anda bereaksi terhadap situasi yang sulit dan tidak biasa. Dengan memberi Anda kode yang salah, dia mungkin ingin melihat apakah Anda membantah. Untuk mengetahui apakah Anda memiliki kepercayaan diri untuk melawan senior Anda dalam situasi yang serupa dengan ini.
PS: Saya tidak tahu kenapa, tetapi saya merasa pewawancara sudah membaca posting ini.
sumber
Kelas abstrak tidak bisa dipakai, tetapi mereka bisa subkelas. Lihat Tautan Ini
Contoh terbaik adalah
Meskipun kelas Calender memiliki metode abstrak getInstance () , tetapi ketika Anda mengatakannya
Calendar calc=Calendar.getInstance();
calc merujuk pada instance kelas dari kelas GregorianCalendar sebagai "GregorianCalendar extends Calendar "
Infact jenis batin annonymous memungkinkan Anda untuk membuat subclass tidak ada nama dari kelas abstrak dan sebuah contoh dari ini.
sumber
Jawaban Teknis
Kelas abstrak tidak dapat dipakai - ini adalah dengan definisi dan desain.
Dari JLS, Bab 8. Kelas:
Dari JSE 6 java doc untuk Classes.newInstance ():
Anda bisa, tentu saja, instantiate subclass konkret dari kelas abstrak (termasuk subclass anonim) dan juga melakukan typecast dari objek referensi ke tipe abstrak.
Sudut Berbeda tentang Ini - Teamplay & Kecerdasan Sosial:
Kesalahpahaman teknis semacam ini sering terjadi di dunia nyata ketika kita berurusan dengan teknologi kompleks dan spesifikasi legalistik.
"Keterampilan Orang" bisa lebih penting di sini daripada "Keterampilan Teknis". Jika secara kompetitif dan agresif mencoba membuktikan sisi argumen Anda, maka Anda secara teori bisa benar, tetapi Anda juga bisa melakukan lebih banyak kerusakan dalam bertarung / merusak "wajah" / menciptakan musuh daripada nilainya. Rekonsiliasi dan pengertianlah dalam menyelesaikan perbedaan Anda. Siapa tahu - mungkin Anda berdua "benar" tetapi bekerja sedikit berbeda makna istilah?
Siapa tahu - meski tidak mungkin, pewawancara mungkin sengaja membuat konflik kecil / kesalahpahaman untuk menempatkan Anda dalam situasi yang menantang dan melihat bagaimana Anda berperilaku secara emosional dan sosial. Bersikap ramah dan konstruktif dengan kolega, ikuti saran dari senior, dan ikuti setelah wawancara untuk menyelesaikan setiap tantangan / kesalahpahaman - melalui email atau panggilan telepon. Menunjukkan Anda termotivasi dan berorientasi pada detail.
sumber
Ini adalah fakta mapan yang tidak
abstract class
bisa diturunkan sebagai orang menjawab.Ketika program mendefinisikan kelas anonim, kompiler sebenarnya menciptakan kelas baru dengan nama yang berbeda (memiliki pola di
EnclosedClassName$n
manan
nomor kelas anonim)Jadi jika Anda mendekompilasi kelas Java ini, Anda akan menemukan kode seperti di bawah ini:
kelasku
poly $ 1.class (kelas yang dihasilkan dari "kelas anonim")
ploly.cass
sumber
Tidak, Anda tidak dapat membuat instan kelas abstrak. Kami hanya instantiate kelas anonim. Dalam kelas abstrak kami mendeklarasikan metode abstrak dan mendefinisikan metode konkret saja.
sumber
Tentang Kelas Abstrak
Tujuan dari kelas abstrak adalah untuk berperilaku seperti basis. Dalam hierarki warisan Anda akan melihat kelas-kelas abstrak di bagian atas.
sumber
Anda dapat mengatakan:
kami tidak dapat membuat instance kelas abstrak, tetapi kami dapat menggunakan
new
kata kunci untuk membuat instance kelas anonim dengan hanya menambahkan{}
sebagai badan implement di akhir kelas abstrak.sumber
Memperluas kelas tidak berarti Anda membuat instance kelas. Sebenarnya, dalam kasus Anda, Anda membuat instance dari subclass.
Saya cukup yakin bahwa kelas abstrak tidak memungkinkan memulai. Jadi, saya katakan tidak: Anda tidak dapat membuat instance kelas abstrak. Tapi, Anda bisa memperpanjang / mewarisinya.
Anda tidak dapat langsung membuat kelas abstrak. Tetapi itu tidak berarti bahwa Anda tidak bisa mendapatkan turunan kelas (bukan turunan kelas turunan abstrak asli) secara tidak langsung. Maksud saya Anda tidak dapat membuat instance kelas abstrak orginial, tetapi Anda dapat:
Jadi Anda mendapatkan akses ke semua metode dan properti di kelas abstrak melalui turunan kelas turunan.
sumber
Tidak mungkin untuk membuat instance kelas abstrak. Apa yang benar-benar dapat Anda lakukan, telah menerapkan beberapa metode umum dalam kelas abstrak dan membiarkan yang lain tidak diimplementasikan (menyatakannya abstrak) dan membiarkan beton turun mengimplementasikannya tergantung pada kebutuhan mereka. Kemudian Anda dapat membuat pabrik, yang mengembalikan instance dari kelas abstrak ini (sebenarnya implementernya). Di pabrik Anda kemudian memutuskan, pelaksana mana yang harus dipilih. Ini dikenal sebagai pola desain pabrik:
Implementer konkret hanya perlu mengimplementasikan metode yang dinyatakan sebagai abstrak, tetapi akan memiliki akses ke logika yang diimplementasikan di kelas-kelas dalam kelas abstrak, yang tidak dinyatakan abstrak:
Lalu akhirnya pabrik terlihat seperti ini:
Penerima AbstractGridManager akan memanggil metode pada dirinya dan mendapatkan logika, diimplementasikan dalam penurunan konkret (dan sebagian dalam metode kelas abstrak) tanpa mengetahui apa implementasi konkret yang ia dapatkan. Ini juga dikenal sebagai inversi kontrol atau injeksi ketergantungan.
sumber
Tidak, kami tidak dapat membuat objek kelas abstrak, tetapi membuat variabel referensi dari kelas abstrak. Variabel referensi digunakan untuk merujuk pada objek dari kelas turunan (Sub kelas dari kelas Abstrak)
Berikut adalah contoh yang menggambarkan konsep ini
Di sini kita melihat bahwa kita tidak dapat membuat objek tipe Gambar tetapi kita dapat membuat variabel referensi tipe Gambar. Di sini kita membuat variabel referensi dari tipe Gambar dan Gambar. Variabel referensi kelas digunakan untuk merujuk ke objek Class Rectangle dan Triangle.
sumber
Sebenarnya kita tidak bisa membuat objek kelas abstrak secara langsung. Apa yang kita buat adalah variabel referensi panggilan abstrak. Variabel referensi digunakan untuk merujuk ke objek kelas yang mewarisi kelas abstrak yaitu subkelas dari kelas abstrak.
sumber