Ingin tahu apa perbedaannya antara yang berikut:
Kasus 1: Kelas Dasar
public void DoIt();
Kasus 1: Kelas turunan
public new void DoIt();
Kasus 2: Kelas Dasar
public virtual void DoIt();
Kasus 2: Kelas turunan
public override void DoIt();
Baik case 1 dan 2 tampaknya memiliki efek yang sama berdasarkan tes yang saya jalankan. Apakah ada perbedaan, atau cara yang disukai?
c#
inheritance
overriding
new-operator
Shiraz Bhaiji
sumber
sumber
Jawaban:
akan memanggil
Derived.DoIt
jika itu menimpaBase.DoIt
.Akan lebih dulu menelepon
Base.DoIt
, laluDerived.DoIt
. Mereka secara efektif dua metode yang sepenuhnya terpisah yang kebetulan memiliki nama yang sama, bukan metode turunan yang menggantikan metode dasar.Sumber: blog Microsoft
sumber
This indicates for the compiler to use the last defined implementation of a method
. bagaimana bisa menemukan implementasi metode yang didefinisikan terakhir ??override
sebuah metode ketika kelas dasar mendefinisikan metode sebagaivirtual
. Kata ituvirtual
adalah kelas dasar yang mengatakan "Hei, ketika saya memanggil metode ini, sebenarnya bisa saja digantikan oleh implementasi yang diturunkan, jadi saya tidak benar-benar tahu sebelumnya apa implementasi metode yang sebenarnya saya panggil saat runtime. Jadivirtual
menandakan adalah pengganti untuk metode. Ini menyiratkan bahwa metode yang tidak ditandai sebagaivirtual
tidak dapat diganti. Tetapi Anda dapat mengganti metode non-virtual di kelas turunan dengan pengubahnew
, hanya dapat diakses di tingkat turunanvirtual : menunjukkan bahwa suatu metode dapat ditimpa oleh pewaris
override : menimpa fungsionalitas metode virtual di kelas dasar, menyediakan fungsionalitas yang berbeda.
baru : menyembunyikan metode asli (yang tidak harus virtual), menyediakan fungsionalitas yang berbeda. Ini hanya boleh digunakan di tempat yang mutlak diperlukan.
Ketika Anda menyembunyikan metode, Anda masih dapat mengakses metode asli dengan melemparkan ke kelas dasar. Ini berguna dalam beberapa skenario, tetapi berbahaya.
sumber
override
dan / ataunew
tanpavirtual
metode induk?Dalam kasus pertama Anda menyembunyikan definisi di kelas induk. Ini berarti bahwa itu hanya akan dipanggil ketika Anda berurusan dengan objek sebagai kelas anak. Jika Anda melemparkan kelas ke tipe induknya, metode induk akan dipanggil. Dalam contoh kedua, metode ini diganti dan akan dipanggil terlepas dari apakah objek dilemparkan sebagai kelas anak atau orang tua.
sumber
coba yang berikut ini: (case1)
Sunting: virtual + override diselesaikan pada saat runtime (jadi override benar-benar menimpa metode virtual), sementara yang baru buat metode baru dengan nama yang sama, dan sembunyikan yang lama, diselesaikan pada waktu kompilasi -> kompiler Anda akan memanggil metode itu ' melihat '
sumber
Dalam kasus 1 jika Anda menggunakan panggilan metode DoIt () dari kelas yang diwarisi sementara jenisnya dinyatakan sebagai kelas dasar Anda akan melihat aksi kelas dasar bahkan.
sumber
Perbedaan antara dua kasus adalah bahwa dalam kasus 1,
DoIt
metode dasar tidak diganti, hanya disembunyikan. Ini artinya tergantung pada jenis variabel, tergantung pada metode mana yang akan dipanggil. Sebagai contoh:Ini bisa sangat membingungkan dan menghasilkan perilaku yang tidak diharapkan dan harus dihindari jika memungkinkan. Jadi cara yang disukai adalah kasus 2.
sumber
Cara saya mengingat kedua kata kunci itu saling bertentangan.
override
:virtual
kata kunci harus didefinisikan untuk mengganti metode. Metode yang menggunakanoverride
kata kunci yang terlepas dari jenis referensi (referensi dari kelas dasar atau kelas turunan) jika itu dipakai dengan kelas dasar, metode kelas dasar berjalan. Kalau tidak, metode kelas turunan berjalan.new
: jika kata kunci digunakan oleh suatu metode, tidak sepertioverride
kata kunci, jenis referensi itu penting. Jika itu dipakai dengan kelas turunan dan tipe referensi adalah kelas dasar, metode kelas dasar berjalan. Jika dipakai dengan kelas turunan dan tipe referensi adalah kelas turunan, metode kelas turunan berjalan. Yaitu, ini kontras denganoverride
kata kunci. En passant, jika Anda lupa atau menghilangkan untuk menambahkan kata kunci baru ke metode, kompiler berperilaku secara default saatnew
kata kunci digunakan.Panggilan utama:
Keluaran:
Contoh kode baru,
Main dengan kode dengan berkomentar satu per satu.
sumber
Jika kata kunci
override
digunakan dalam turunan kelas maka menimpa metode induknya.Jika Kata Kunci
new
digunakan dalam turunan kelas maka turunkan metode disembunyikan oleh metode induk.sumber
Saya memiliki pertanyaan yang sama dan ini benar-benar membingungkan, Anda harus mempertimbangkan bahwa mengganti dan kata kunci baru hanya berfungsi dengan objek dari kelas tipe dasar dan nilai kelas turunan. Dalam hal ini hanya Anda yang akan melihat efek override dan baru: Jadi jika Anda memiliki
class A
danB
,B
mewarisi dariA
, maka Anda instantiate objek seperti ini:Sekarang memanggil metode akan mempertimbangkan keadaannya. Override : berarti ia memperluas fungsi metode, kemudian menggunakan metode di kelas turunan, sedangkan yang baru memberitahu kompiler untuk menyembunyikan metode di kelas turunan dan menggunakan metode di kelas dasar sebagai gantinya. Ini adalah pemandangan yang sangat bagus untuk subjek itu:
https://msdn.microsoft.com/EN-US/library/ms173153%28v=VS.140,d=hv.2%29.aspx?f=255&MSPPError=-2147217396
sumber
Artikel di bawah ini ada di vb.net tapi saya pikir penjelasan tentang penggantian baru vs sangat mudah dipahami.
https://www.codeproject.com/articles/17477/the-dark-shadow-of-overrides
Di beberapa titik dalam artikel, ada kalimat ini:
Jawaban yang diterima untuk pertanyaan ini sempurna tetapi saya pikir artikel ini memberikan contoh yang baik untuk menambahkan makna yang lebih baik tentang perbedaan antara dua kata kunci ini.
sumber
Dari semua itu, baru adalah yang paling membingungkan. Dengan bereksperimen, kata kunci baru seperti memberi pengembang pilihan untuk menimpa implementasi kelas pewarisan dengan implementasi kelas dasar dengan secara eksplisit mendefinisikan jenisnya. Ini seperti berpikir sebaliknya.
Dalam contoh di bawah ini, hasilnya akan mengembalikan "Hasil turunan" hingga jenisnya secara eksplisit didefinisikan sebagai uji BaseClass, hanya kemudian "Hasil dasar" akan dikembalikan.
sumber
Perbedaan fungsional tidak akan ditampilkan dalam tes ini:
Dalam contoh ini, Doit yang dipanggil adalah yang Anda harapkan untuk dipanggil.
Untuk melihat perbedaannya, Anda harus melakukan ini:
Anda akan melihat apakah Anda menjalankan tes itu dalam kasus 1 (seperti yang Anda definisikan),
DoIt()
inBaseClass
disebut, dalam kasus 2 (seperti yang Anda definisikan),DoIt()
inDerivedClass
disebut.sumber
Pada kasus pertama itu akan memanggil metode DoIt () kelas turunan karena kata kunci baru menyembunyikan metode DoIt () kelas dasar.
Pada kasus kedua ini akan memanggil DoIt () overriden ()
mari buat instance dari kelas-kelas ini
Semuanya diharapkan di atas. Biarkan atur instanceB dan instanceC ke instanceA dan panggil metode DoIt () dan periksa hasilnya.
sumber
Semua kombinasi tidak ada, virtual, override, baru dan abstrak:
sumber