Mengapa tidak mungkin mengganti metode statis?
Jika memungkinkan, silakan gunakan contoh.
java
static
overriding
static-methods
sgokhales
sumber
sumber
Parent p = new Child()
dan kemudianp.childOverriddenStaticMethod()
kompiler akan menyelesaikannyaParent.childOverriddenStaticMethod()
dengan melihat tipe referensi.Jawaban:
Overriding tergantung pada memiliki instance kelas. Inti dari polimorfisme adalah bahwa Anda dapat mensubclass sebuah kelas dan objek yang mengimplementasikan subclass tersebut akan memiliki perilaku yang berbeda untuk metode yang sama yang didefinisikan dalam superclass (dan diganti dalam subclass). Metode statis tidak terkait dengan instance kelas apa pun sehingga konsepnya tidak berlaku.
Ada dua pertimbangan yang mendorong desain Java yang memengaruhi hal ini. Salah satunya adalah kekhawatiran dengan kinerja: ada banyak kritik terhadap Smalltalk tentang itu terlalu lambat (pengumpulan sampah dan panggilan polimorfik menjadi bagian dari itu) dan pencipta Jawa bertekad untuk menghindari itu. Lain adalah keputusan bahwa target audiens untuk Java adalah pengembang C ++. Membuat metode statis bekerja seperti yang mereka lakukan memiliki manfaat keakraban untuk programmer C ++ dan juga sangat cepat, karena tidak perlu menunggu sampai runtime untuk mengetahui metode mana yang harus dipanggil.
sumber
objects
) memungkinkan kelebihan metode.obj.staticMethod()
) - yang diizinkan dan menggunakan tipe waktu kompilasi. Ketika panggilan statis dalam metode non-statis kelas, objek "saat ini" bisa menjadi tipe turunan kelas - tetapi metode statis yang didefinisikan pada tipe turunan tidak dipertimbangkan (mereka berada dalam tipe run-time hirarki).Secara pribadi saya pikir ini adalah cacat dalam desain Java. Ya, ya, saya mengerti bahwa metode non-statis dilampirkan ke instance sementara metode statis dilampirkan ke kelas, dll. Namun, pertimbangkan kode berikut:
Kode ini tidak akan berfungsi seperti yang Anda harapkan. Yakni, SpecialEmployee's mendapatkan bonus 2% seperti halnya karyawan biasa. Tetapi jika Anda menghapus "statis", maka SpecialEmployee's mendapatkan bonus 3%.
(Harus diakui, contoh ini adalah gaya pengkodean yang buruk karena dalam kehidupan nyata Anda mungkin ingin pengganda bonus berada di basis data di suatu tempat daripada di-kode-keras. Tapi itu hanya karena saya tidak ingin mengurangi contoh dengan banyak kode tidak relevan dengan intinya.)
Tampaknya masuk akal bagi saya bahwa Anda mungkin ingin menjadikan getBonusMultiplier statis. Mungkin Anda ingin dapat menampilkan pengganda bonus untuk semua kategori karyawan, tanpa harus memiliki instance karyawan di setiap kategori. Apa gunanya mencari contoh contoh seperti itu? Bagaimana jika kita membuat kategori karyawan baru dan belum memiliki karyawan yang ditugaskan? Ini secara logis merupakan fungsi statis.
Tapi itu tidak berhasil.
Dan ya, ya, saya bisa memikirkan sejumlah cara untuk menulis ulang kode di atas untuk membuatnya berfungsi. Maksud saya bukanlah menciptakan masalah yang tidak dapat diselesaikan, tetapi menciptakan jebakan bagi programmer yang tidak waspada, karena bahasa tersebut tidak berperilaku seperti yang saya kira orang yang masuk akal harapkan.
Mungkin jika saya mencoba menulis kompiler untuk bahasa OOP, saya akan segera melihat mengapa mengimplementasikannya sehingga fungsi statis dapat ditimpa akan sulit atau tidak mungkin.
Atau mungkin ada beberapa alasan bagus mengapa Jawa berlaku seperti ini. Adakah yang bisa menunjukkan keunggulan perilaku ini, beberapa kategori masalah yang dibuat lebih mudah dengan ini? Maksud saya, jangan hanya mengarahkan saya ke spesifikasi bahasa Java dan mengatakan "lihat, ini didokumentasikan bagaimana perilakunya". Saya tahu itu. Tetapi apakah ada alasan bagus mengapa itu HARUS berperilaku seperti ini? (Selain itu jelas "membuatnya bekerja dengan benar terlalu sulit" ...)
Memperbarui
@VicKirk: Jika Anda maksudkan ini adalah "desain yang buruk" karena tidak sesuai dengan bagaimana Java menangani statika, jawaban saya adalah, "Ya, tentu saja, ya." Seperti yang saya katakan di posting asli saya, itu tidak berfungsi. Tetapi jika Anda maksudkan bahwa itu adalah desain yang buruk dalam arti bahwa akan ada sesuatu yang secara fundamental salah dengan bahasa tempat ini bekerja, yaitu di mana statika dapat ditimpa seperti fungsi virtual, bahwa ini entah bagaimana akan memperkenalkan ambiguitas atau tidak mungkin untuk menerapkan secara efisien atau semacamnya, saya menjawab, "Mengapa? Apa yang salah dengan konsep itu?"
Saya pikir contoh yang saya berikan adalah hal yang sangat alami untuk ingin dilakukan. Saya memiliki kelas yang memiliki fungsi yang tidak bergantung pada data instance apa pun, dan yang saya mungkin ingin sebut independen dari sebuah instance, serta ingin menelepon dari dalam metode instance. Mengapa ini tidak berhasil? Saya telah mengalami situasi ini beberapa kali selama bertahun-tahun. Dalam praktiknya saya menyiasatinya dengan membuat fungsi virtual, dan kemudian membuat metode statis yang satu-satunya tujuan dalam hidup adalah menjadi metode statis yang meneruskan panggilan ke metode virtual dengan contoh dummy. Itu sepertinya cara yang sangat bundaran untuk sampai ke sana.
sumber
someStatic()
dan B meluas A, makaB.someMethod()
mengikat ke metode dalam A. Jika saya kemudian menambahkansomeStatic()
ke B, kode panggilan masih memanggilA.someStatic()
sampai saya mengkompilasi ulang kode panggilan. Juga itu mengejutkan saya bahwabInstance.someStatic()
menggunakan menyatakan jenis bInstance, bukan tipe runtime karena mengikat di kompilasi tidak link sehinggaA bInstance; ... bInstance.someStatic()
memanggil A.someStatic () jika jika B.someStatic () ada.Jawaban singkatnya adalah: itu sepenuhnya mungkin, tetapi Java tidak melakukannya.
Berikut adalah beberapa kode yang menggambarkan keadaan terkini di Jawa:
File
Base.java
:File
Child.java
:Jika Anda menjalankan ini (saya melakukannya di Mac, dari Eclipse, menggunakan Java 1.6) Anda akan mendapatkan:
Di sini, satu - satunya kasus yang mungkin mengejutkan (dan yang menjadi pertanyaan adalah) adalah kasus pertama :
"Tipe run-time tidak digunakan untuk menentukan metode statis mana yang dipanggil, bahkan ketika dipanggil dengan instance objek (
obj.staticMethod()
)."dan kasus terakhir :
"Ketika memanggil metode statis dari dalam metode objek kelas, metode statis yang dipilih adalah yang dapat diakses dari kelas itu sendiri dan bukan dari kelas yang mendefinisikan jenis run-time objek."
Memanggil dengan instance objek
Panggilan statis diselesaikan pada waktu kompilasi, sedangkan panggilan metode non-statis diselesaikan pada saat dijalankan. Perhatikan bahwa meskipun metode statis diwariskan (dari orangtua) mereka tidak diganti (oleh anak). Ini bisa menjadi kejutan jika Anda mengharapkan sebaliknya.
Memanggil dari dalam metode objek
Panggilan metode objek diselesaikan menggunakan tipe run-time, tetapi panggilan metode statis ( kelas ) diselesaikan dengan menggunakan tipe waktu kompilasi (dideklarasikan).
Mengubah aturan
Untuk mengubah aturan-aturan ini, sehingga panggilan terakhir dalam contoh yang dipanggil
Child.printValue()
, panggilan statis harus disediakan dengan tipe pada saat run-time, daripada kompiler menyelesaikan panggilan pada saat kompilasi dengan kelas objek yang dideklarasikan (atau konteks). Panggilan statis kemudian dapat menggunakan hirarki tipe (dinamis) untuk menyelesaikan panggilan, seperti yang dilakukan metode panggilan objek hari ini.Ini dengan mudah bisa dilakukan (jika kita mengubah Java: -O), dan sama sekali tidak masuk akal, bagaimanapun, ia memiliki beberapa pertimbangan menarik.
Pertimbangan utama adalah bahwa kita perlu memutuskan panggilan metode statis mana yang harus melakukan ini.
Saat ini, Java memiliki "kekhasan" dalam bahasa di mana
obj.staticMethod()
panggilan diganti denganObjectClass.staticMethod()
panggilan (biasanya dengan peringatan). [ Catatan:ObjectClass
adalah tipe waktu kompilasiobj
.] Ini akan menjadi kandidat yang baik untuk mengganti dengan cara ini, dengan menggunakan tipe run-timeobj
.Jika kita lakukan itu akan membuat badan metode lebih sulit untuk dibaca: panggilan statis di kelas induk berpotensi secara dinamis "dialihkan kembali". Untuk menghindari ini, kita harus memanggil metode statis dengan nama kelas - dan ini membuat panggilan lebih jelas diselesaikan dengan hierarki jenis waktu kompilasi (seperti sekarang).
Cara lain untuk menggunakan metode statis lebih rumit:
this.staticMethod()
harus berarti sama denganobj.staticMethod()
, mengambil jenis run-timethis
. Namun, ini dapat menyebabkan beberapa sakit kepala dengan program yang ada, yang memanggil metode statis (tampaknya lokal) tanpa dekorasi (yang bisa dibilang setara denganthis.method()
).Jadi bagaimana dengan panggilan tanpa hiasan
staticMethod()
? Saya menyarankan mereka melakukan hal yang sama seperti hari ini, dan menggunakan konteks kelas lokal untuk memutuskan apa yang harus dilakukan. Kalau tidak, akan timbul kebingungan besar. Tentu saja itu berarti bahwamethod()
akan berartithis.method()
jikamethod
itu metode non-statis, danThisClass.method()
jikamethod
itu metode statis. Ini adalah sumber kebingungan lainnya.Pertimbangan lainnya
Jika kami mengubah perilaku ini (dan membuat panggilan statis yang berpotensi non-lokal secara dinamis), kami mungkin ingin meninjau kembali makna
final
,private
danprotected
sebagai kualifikasi padastatic
metode kelas. Kita kemudian harus membiasakan diri dengan fakta bahwaprivate static
danpublic final
metode tidak diganti, dan karena itu dapat diselesaikan dengan aman pada waktu kompilasi, dan "aman" untuk dibaca sebagai referensi lokal.sumber
Sebenarnya kami salah.
Meskipun Java tidak memungkinkan Anda untuk menimpa metode statis secara default, jika Anda melihat dengan teliti melalui dokumentasi kelas dan metode kelas di Jawa, Anda masih bisa menemukan cara untuk meniru metode statis menimpa dengan mengikuti solusi berikut:
Output yang dihasilkan:
apa yang kami coba capai :)
Bahkan jika kita mendeklarasikan variabel ketiga Carl sebagai RegularEmployee dan menugaskan contoh SpecialEmployee, kita masih akan memiliki panggilan metode RegularEmployee dalam kasus pertama dan panggilan metode SpecialEmployee dalam kasus kedua
lihat saja konsol keluaran:
;)
sumber
Metode statis diperlakukan sebagai global oleh JVM, tidak ada terikat pada contoh objek sama sekali.
Secara konseptual dapat dimungkinkan jika Anda dapat memanggil metode statis dari objek kelas (seperti dalam bahasa seperti Smalltalk) tetapi tidak demikian halnya di Jawa.
EDIT
Anda dapat membebani metode statis, tidak apa-apa. Tetapi Anda tidak dapat mengganti metode statis, karena kelas bukan objek kelas satu. Anda bisa menggunakan refleksi untuk mendapatkan kelas dari suatu objek pada saat run-time, tetapi objek yang Anda dapatkan tidak sejajar dengan hierarki kelas.
Anda dapat merefleksikan kelas, tetapi berhenti di sana. Anda tidak menggunakan metode statis dengan menggunakan
clazz1.staticMethod()
, tetapi menggunakanMyClass.staticMethod()
. Metode statis tidak terikat pada objek dan karenanya tidak ada gagasan tentangthis
atausuper
dalam metode statis. Metode statis adalah fungsi global; sebagai konsekuensinya juga tidak ada gagasan polimorfisme dan, oleh karena itu, metode penimpaan tidak masuk akal.Tapi ini bisa dimungkinkan jika
MyClass
ada objek saat run-time di mana Anda memanggil metode, seperti dalam Smalltalk (atau mungkin JRuby sebagai satu komentar menyarankan, tapi saya tidak tahu apa-apa tentang JRuby).Oh ya, satu hal lagi. Anda dapat menggunakan metode statis melalui objek
obj1.staticMethod()
tetapi itu benar-benar sintaksis untukMyClass.staticMethod()
dan harus dihindari. Biasanya memunculkan peringatan dalam IDE modern. Saya tidak tahu mengapa mereka pernah mengizinkan pintasan ini.sumber
clazz2 instanceof clazz1
dengan benar, Anda dapat menggunakanclass2.isAssignableFrom(clazz1)
, yang saya percaya akan mengembalikan true dalam contoh Anda.Metode penimpaan dimungkinkan oleh pengiriman dinamis , yang berarti bahwa jenis objek yang dideklarasikan tidak menentukan perilakunya, melainkan jenis runtime-nya:
Meskipun keduanya
lassie
dankermit
dideklarasikan sebagai objek bertipeAnimal
, perilaku (metode.speak()
) mereka bervariasi karena pengiriman dinamis hanya akan mengikat pemanggilan metode.speak()
pada implementasi pada saat run time - bukan pada waktu kompilasi.Sekarang, di sinilah
static
kata kunci mulai masuk akal: kata "statis" adalah antonim untuk "dinamis". Jadi alasan mengapa Anda tidak dapat mengganti metode statis adalah karena tidak ada pengiriman dinamis pada anggota statis - karena statis secara harfiah berarti "tidak dinamis". Jika mereka dikirim secara dinamis (dan dengan demikian bisa ditimpa)static
kata kunci tidak akan masuk akal lagi.sumber
Iya. Praktis Java memungkinkan metode statis utama, dan Tidak secara teoritis jika Anda menimpa metode statis di Jawa maka itu akan mengkompilasi dan berjalan dengan lancar tetapi akan kehilangan Polimorfisme yang merupakan properti dasar Jawa. Anda akan Baca Di Mana Saja bahwa tidak mungkin untuk mencoba membuat dan menjalankan sendiri. Anda akan mendapatkan jawaban Anda. mis. Jika Anda Memiliki Hewan Kelas dan metode statis, makan () dan Anda Override metode statis itu dalam Subkelasnya, beri nama Dog. Kemudian ketika di mana pun Anda Menetapkan objek Anjing ke Referensi Hewan dan memanggil eat () menurut Java Dog eat () seharusnya dipanggil tetapi dalam makan Overriding Animals statis () akan Dipanggil.
Menurut Prinsip Polimorfisme Jawa, Keluaran Seharusnya
Dog Eating
.Tetapi hasilnya berbeda karena untuk mendukung Polymorphism Java menggunakan Late Binding yang berarti metode hanya dipanggil pada saat run-time tetapi tidak dalam kasus metode statis. Dalam metode statis, kompiler memanggil metode pada waktu kompilasi daripada pada saat run-time, jadi kami mendapatkan metode sesuai dengan referensi dan tidak sesuai dengan objek referensi yang mengandung itu sebabnya Anda dapat mengatakan Secara praktis mendukung overring statis tetapi secara teoritis, tidak 't.
sumber
overriding dicadangkan untuk anggota misalnya untuk mendukung perilaku polimorfik. anggota kelas statis bukan milik instance tertentu. sebagai gantinya, anggota statis menjadi anggota kelas dan akibatnya pengesampingan tidak didukung karena subkelas hanya mewarisi anggota yang dilindungi dan publik dan bukan anggota statis. Anda mungkin ingin mendefinisikan pabrik inerface dan riset dan / atau pola desain strategi untuk mengevaluasi pendekatan alternatif.
sumber
Di Jawa (dan banyak bahasa OOP, tapi saya tidak bisa berbicara untuk semua; dan beberapa tidak memiliki statis sama sekali) semua metode memiliki tanda tangan tetap - parameter dan tipe. Dalam metode virtual, parameter pertama tersirat: referensi ke objek itu sendiri dan ketika dipanggil dari dalam objek, kompiler secara otomatis menambahkan
this
.Tidak ada perbedaan untuk metode statis - mereka masih memiliki tanda tangan tetap. Namun, dengan mendeklarasikan metode statis, Anda telah secara eksplisit menyatakan bahwa kompiler tidak boleh menyertakan parameter objek tersirat pada awal tanda tangan itu. Oleh karena itu, kode lain apa pun yang memanggil ini harus tidak boleh mencoba untuk menempatkan referensi ke objek di tumpukan . Jika memang melakukan itu, maka eksekusi metode tidak akan bekerja karena parameter akan berada di tempat yang salah - digeser oleh satu - di stack.
Karena perbedaan antara keduanya; Metode virtual selalu memiliki referensi ke objek konteks (yaitu
this
) sehingga maka dimungkinkan untuk referensi apa pun di dalam tumpukan yang dimiliki oleh instance objek tersebut. Tetapi dengan metode statis, karena tidak ada referensi yang lewat, metode itu tidak dapat mengakses variabel objek dan metode apa pun karena konteksnya tidak diketahui.Jika Anda berharap bahwa Java akan mengubah definisi sehingga konteks objek diteruskan untuk setiap metode, statis atau virtual, maka Anda pada dasarnya hanya memiliki metode virtual.
Ketika seseorang bertanya dalam komentar pada op - apa alasan dan tujuan Anda menginginkan fitur ini?
Saya tidak tahu banyak tentang Ruby, karena ini disebutkan oleh OP, saya melakukan riset. Saya melihat bahwa di kelas Ruby benar-benar jenis objek khusus dan seseorang dapat membuat (bahkan secara dinamis) metode baru. Kelas adalah objek kelas penuh di Ruby, mereka bukan di Jawa. Ini adalah sesuatu yang harus Anda terima ketika bekerja dengan Java (atau C #). Ini bukan bahasa dinamis, meskipun C # menambahkan beberapa bentuk dinamis. Pada kenyataannya, Ruby tidak memiliki metode "statis" sejauh yang saya bisa temukan - dalam hal ini adalah metode pada objek kelas singleton. Anda kemudian dapat menimpa singleton ini dengan kelas baru dan metode di objek kelas sebelumnya akan memanggil yang didefinisikan di kelas baru (benar?). Jadi jika Anda memanggil metode dalam konteks kelas asli itu masih hanya akan menjalankan statika asli, tetapi memanggil metode dalam kelas turunan, akan memanggil metode baik dari induk atau sub-kelas. Menarik dan saya bisa melihat beberapa nilai di dalamnya. Dibutuhkan pola pikir yang berbeda.
Karena Anda bekerja di Jawa, Anda harus menyesuaikan dengan cara melakukan hal-hal tersebut. Kenapa mereka melakukan ini? Yah, mungkin untuk meningkatkan kinerja pada saat itu berdasarkan pada teknologi dan pemahaman yang tersedia. Bahasa komputer terus berkembang. Kembalilah cukup jauh dan tidak ada yang namanya OOP. Di masa depan, akan ada ide-ide baru lainnya.
EDIT : Satu komentar lain. Sekarang saya melihat perbedaannya dan saya sebagai pengembang Java / C #, saya bisa mengerti mengapa jawaban yang Anda dapatkan dari pengembang Java mungkin membingungkan jika Anda berasal dari bahasa seperti Ruby.
static
Metode Java tidak sama denganclass
metode Ruby . Pengembang Java akan mengalami kesulitan memahami hal ini, seperti halnya mereka yang kebanyakan bekerja dengan bahasa seperti Ruby / Smalltalk. Saya dapat melihat bagaimana ini juga akan sangat membingungkan dengan fakta bahwa Java juga menggunakan "metode kelas" sebagai cara lain untuk berbicara tentang metode statis tetapi istilah yang sama digunakan secara berbeda oleh Ruby. Java tidak memiliki metode kelas gaya Ruby (maaf); Ruby tidak memiliki metode statis gaya Java yang benar-benar hanya fungsi gaya prosedural lama, seperti yang ditemukan dalam C.By the way - terima kasih atas pertanyaannya! Saya belajar sesuatu yang baru untuk saya hari ini tentang metode kelas (gaya Ruby).
sumber
Yah ... jawabannya adalah TIDAK jika Anda berpikir dari perspektif bagaimana seharusnya metode overriden di Jawa. Tapi, Anda tidak mendapatkan kesalahan kompilator jika Anda mencoba mengganti metode statis. Itu berarti, jika Anda mencoba menimpa, Java tidak menghentikan Anda melakukan itu; tetapi Anda tentu tidak mendapatkan efek yang sama seperti yang Anda dapatkan untuk metode non-statis. Meng-override di Jawa berarti bahwa metode tertentu akan dipanggil berdasarkan jenis run time objek dan bukan pada tipe waktu kompilasi objek (yang merupakan kasus dengan metode statis overriden). Oke ... ada tebakan untuk alasan mengapa mereka berperilaku aneh? Karena mereka adalah metode kelas dan karenanya akses ke mereka selalu diselesaikan selama waktu kompilasi hanya menggunakan informasi tipe waktu kompilasi.
Contoh : mari kita coba lihat apa yang terjadi jika kita mencoba mengganti metode statis: -
Output : -
SuperClass: inside staticMethod
SuperClass: inside staticMethod
SubClass: inside staticMethod
Perhatikan baris kedua dari output. Seandainya staticMethod di-override baris ini seharusnya identik dengan baris ketiga saat kita memanggil 'staticMethod ()' pada objek Runtime Type sebagai 'SubClass' dan bukan sebagai 'SuperClass'. Ini mengonfirmasi bahwa metode statis selalu diselesaikan menggunakan informasi jenis waktu kompilasi saja.
sumber
Secara umum tidak masuk akal untuk mengizinkan 'menimpa' metode statis karena tidak akan ada cara yang baik untuk menentukan mana yang akan dipanggil saat runtime. Mengambil contoh Karyawan, jika kita memanggil RegularEmployee.getBonusMultiplier () - metode mana yang seharusnya dijalankan?
Dalam kasus Jawa, orang dapat membayangkan definisi bahasa di mana dimungkinkan untuk 'menimpa' metode statis selama mereka dipanggil melalui instance objek. Namun, semua ini akan dilakukan adalah menerapkan kembali metode kelas reguler, menambahkan redundansi ke bahasa tanpa benar-benar menambahkan manfaat apa pun.
sumber
Dengan mengesampingkan kita dapat membuat sifat polimorfik tergantung pada jenis objek. Metode statis tidak ada hubungannya dengan objek. Jadi java tidak dapat mendukung metode statis utama.
sumber
Saya suka dan gandakan komentar Jay ( https://stackoverflow.com/a/2223803/1517187 ).
Saya setuju bahwa ini adalah desain Java yang buruk.
Banyak bahasa lain mendukung metode statis utama, seperti yang kita lihat di komentar sebelumnya. Saya merasa Jay juga datang ke Jawa dari Delphi seperti saya.
Delphi (Object Pascal) adalah bahasa pertama yang mengimplementasikan OOP.
Jelas bahwa banyak orang memiliki pengalaman dengan bahasa itu karena di masa lalu hanya bahasa untuk menulis produk GUI komersial. Dan - ya, kita bisa mengesampingkan metode statis di Delphi. Sebenarnya, metode statis dalam Delphi disebut "metode kelas", sedangkan Delphi memiliki konsep yang berbeda "metode statis Delphi" yang merupakan metode dengan penjilidan awal. Untuk mengganti metode Anda harus menggunakan pengikatan akhir, mendeklarasikan direktif "virtual". Jadi itu sangat mudah dan intuitif dan saya harapkan ini di Jawa.
sumber
Apa gunanya mengganti metode statis. Anda tidak dapat memanggil metode statis melalui instance.
EDIT: Tampaknya melalui pengawasan yang tidak menguntungkan dalam desain bahasa, Anda dapat memanggil metode statis melalui instance. Umumnya tidak ada yang melakukan itu. Salahku.
sumber
variable.staticMethod()
, bukannyaClass.staticMethod()
, di manavariable
variabel dengan tipe yang dideklarasikanClass
. Saya setuju itu desain bahasa yang buruk.Overriding di Jawa berarti bahwa metode tertentu akan dipanggil berdasarkan pada tipe runtime objek dan bukan pada tipe waktu kompilasi (yang merupakan kasus dengan metode statis yang diganti). Karena metode statis adalah metode kelas, mereka bukan metode instan sehingga tidak ada hubungannya dengan fakta referensi mana yang menunjuk ke Objek atau instance mana, karena karena sifat metode statis itu milik kelas tertentu. Anda dapat mendeklarasikan ulang di subclass tetapi subclass itu tidak akan tahu apa-apa tentang metode statis kelas induk karena, seperti yang saya katakan, itu hanya khusus untuk kelas yang telah dideklarasikan. Mengakses mereka menggunakan referensi objek hanyalah kebebasan ekstra yang diberikan oleh perancang Jawa dan kita tentu tidak boleh berpikir untuk menghentikan praktik itu hanya ketika mereka membatasi lebih detail dan contoh http://faisalbhagat.blogspot.com/2014/09/method-overriding-and-method-hiding.html
sumber
Dengan mengesampingkan, Anda mencapai polimorfisme dinamis. Ketika Anda mengatakan metode statis utama, kata-kata yang Anda coba gunakan bertentangan.
Kata statis - waktu kompilasi, penggantian digunakan untuk polimorfisme dinamis. Keduanya sifatnya berlawanan, dan karenanya tidak dapat digunakan bersama.
Perilaku polimorfik dinamis muncul ketika seorang programmer menggunakan objek dan mengakses metode instance. JRE akan memetakan metode instance yang berbeda dari kelas yang berbeda berdasarkan pada jenis objek yang Anda gunakan.
Ketika Anda mengatakan mengganti metode statis, metode statis akan kita akses dengan menggunakan nama kelas, yang akan ditautkan pada waktu kompilasi, jadi tidak ada konsep menghubungkan metode saat runtime dengan metode statis. Jadi istilah "mengesampingkan" metode statis itu sendiri tidak ada artinya.
Catatan: bahkan jika Anda mengakses metode kelas dengan objek, masih kompiler java cukup cerdas untuk mengetahuinya, dan akan melakukan tautan statis.
sumber
Box.createBox
lebih masuk akal daripadaBoxFactory.createBox
, dan merupakan pola yang tidak dapat dihindari ketika perlu untuk memeriksa kesalahan konstruksi tanpa melemparkan pengecualian (konstruktor tidak dapat gagal, mereka hanya dapat mematikan proses / melempar pengecualian), sedangkan metode statis dapat mengembalikan nol pada kegagalan, atau bahkan menerima panggilan balik keberhasilan / kesalahan untuk menulis sesuatu seperti hastebin.com/codajahati.java .Jawaban dari pertanyaan ini sederhana, metode atau variabel yang ditandai sebagai statis hanya milik kelas saja, sehingga metode statis tidak dapat diwariskan dalam sub kelas karena mereka hanya milik kelas super saja.
sumber
Solusi mudah: Gunakan instance singleton. Ini akan memungkinkan penggantian dan pewarisan.
Dalam sistem saya, saya memiliki kelas SingletonsRegistry, yang mengembalikan instance untuk Kelas yang lulus. Jika instance tidak ditemukan, itu dibuat.
Kelas bahasa Haxe:
sumber
Singleton.get()
. Registri hanya overhead boilerplate, dan menghalangi GC di kelas.Metode statis, variabel, blok atau kelas bersarang milik seluruh kelas daripada objek.
Metode di Jawa digunakan untuk mengekspos perilaku Obyek / Kelas. Di sini, karena metode ini statis (yaitu, metode statis digunakan untuk mewakili perilaku kelas saja.) Mengubah / mengesampingkan perilaku seluruh kelas akan melanggar fenomena salah satu pilar dasar pemrograman berorientasi objek yaitu, kohesi tinggi . (ingat konstruktor adalah jenis metode khusus di Jawa.)
Kohesi Tinggi - Satu kelas seharusnya hanya memiliki satu peran. Sebagai contoh: Kelas mobil harus menghasilkan hanya objek mobil dan bukan sepeda, truk, pesawat dll. Tapi kelas Mobil mungkin memiliki beberapa fitur (perilaku) yang hanya dimiliki oleh dirinya sendiri.
Oleh karena itu, sambil merancang bahasa pemrograman java. Perancang bahasa berpikir untuk memungkinkan pengembang untuk menjaga perilaku kelas hanya dengan membuat metode statis.
Kode bagian di bawah ini mencoba menimpa metode statis, tetapi tidak akan menemukan kesalahan kompilasi.
Ini karena, di sini kita tidak mengganti metode tetapi kita hanya mendeklarasikannya kembali. Java memungkinkan deklarasi ulang suatu metode (statis / non-statis).
Menghapus kata kunci statis dari metode getVehileNumber () kelas Mobil akan mengakibatkan kesalahan kompilasi, Karena, kami mencoba mengubah fungsionalitas metode statis yang hanya milik kelas Kendaraan.
Juga, Jika getVehileNumber () dideklarasikan sebagai final maka kode tidak akan dikompilasi, Karena kata kunci terakhir membatasi programmer dari menyatakan kembali metode.
Secara keseluruhan, ini adalah perancang perangkat lunak terkini untuk tempat menggunakan metode statis. Saya pribadi lebih suka menggunakan metode statis untuk melakukan beberapa tindakan tanpa membuat instance kelas apa pun. Kedua, menyembunyikan perilaku kelas dari dunia luar.
sumber
Berikut ini penjelasan sederhana. Metode statis dikaitkan dengan kelas sedangkan metode contoh dikaitkan dengan objek tertentu. Override memungkinkan memanggil implementasi yang berbeda dari metode override yang terkait dengan objek tertentu. Jadi kontra-intuitif untuk menimpa metode statis yang bahkan tidak terkait dengan objek tetapi kelas itu sendiri di tempat pertama. Jadi metode statis tidak bisa diganti berdasarkan objek apa yang memanggilnya, itu akan selalu dikaitkan dengan kelas tempat ia dibuat.
sumber
public abstract IBox createBox();
antarmuka IBox di dalam? Box dapat mengimplementasikan IBox untuk mengesampingkan createBox, dan membuat kreasi objek menghasilkan IBox yang valid, jika tidak mengembalikan null. Konstruktor tidak dapat mengembalikan "null" dan karena itu Anda dipaksa untuk (1) menggunakan pengecualian di mana-mana (apa yang kita lakukan sekarang), atau (2) membuat kelas pabrik yang melakukan apa yang saya katakan sebelumnya tetapi dengan cara yang tidak masuk akal bagi pemula atau ahli Jawa (Yang kami juga lakukan sekarang). Metode statis yang tidak diimplementasikan menyelesaikan ini.Sekarang melihat jawaban di atas semua orang tahu bahwa kita tidak dapat menimpa metode statis, tetapi orang tidak boleh salah paham tentang konsep mengakses metode statis dari subclass .
Sebagai Contoh, lihat kode di bawah ini: -
Keluaran:-
Terima kasih
sumber
Kode berikut menunjukkan bahwa itu mungkin:
sumber
osm
adalahOverridenStaticMeth
tidakOverrideStaticMeth
.