Ketika kita membuat kelas yang mewarisi dari kelas abstrak dan ketika kita menerapkan kelas abstrak yang diwarisi mengapa kita harus menggunakan kata kunci override?
public abstract class Person
{
public Person()
{
}
protected virtual void Greet()
{
// code
}
protected abstract void SayHello();
}
public class Employee : Person
{
protected override void SayHello() // Why is override keyword necessary here?
{
throw new NotImplementedException();
}
protected override void Greet()
{
base.Greet();
}
}
Karena metode ini dinyatakan abstrak di kelas induknya, itu tidak memiliki implementasi di kelas induk, jadi mengapa kata kunci menimpa diperlukan di sini?
new
kunci` ... Anda juga akan mendapatkan kesalahan" tidak ada metode yang menggantikan metode kelas dasar ".Jawaban:
"Mengapa?" pertanyaan seperti ini bisa sulit dijawab karena tidak jelas. Saya akan berasumsi bahwa pertanyaan Anda adalah "argumen apa yang dapat dibuat selama desain bahasa untuk menyatakan posisi yang diperlukan
override
kata kunci ?"Mari kita mulai dengan mengambil langkah mundur. Dalam beberapa bahasa, katakanlah, Java, metode adalah virtual secara default dan diganti secara otomatis. Para perancang C # menyadari hal ini dan menganggapnya sebagai cacat kecil di Jawa. C # bukan "Java dengan bagian-bagian bodoh dihilangkan" seperti yang dikatakan beberapa orang, tetapi para perancang C # ingin belajar dari titik-titik desain C, C ++ dan Java yang bermasalah, dan tidak mereplikasi mereka dalam C #.
Desainer C # dianggap sebagai sumber bug utama; Lagi pula, ini adalah cara untuk mengubah perilaku kode yang sudah ada dan diuji , dan itu berbahaya. Mengesampingkan bukanlah sesuatu yang harus dilakukan dengan santai atau kebetulan; itu harus dirancang oleh seseorang yang berpikir keras tentangnya . Itu sebabnya metode tidak virtual secara default, dan mengapa Anda diminta untuk mengatakan bahwa Anda mengganti metode.
Itulah alasan dasarnya. Kita sekarang bisa masuk ke beberapa alasan yang lebih maju.
Jawaban StriplingWarrior memberikan potongan pertama yang baik untuk membuat argumen yang lebih maju. Penulis kelas turunan mungkin tidak diberi tahu tentang kelas dasar, mungkin berniat untuk membuat metode baru, dan kami tidak boleh mengizinkan pengguna untuk menimpa secara tidak sengaja .
Meskipun poin ini masuk akal, ada sejumlah tandingan, seperti:
Mari kita buat argumen yang lebih maju tentang hal ini. Dalam keadaan apa penulis kelas turunan dapat dimaafkan karena tidak mengetahui apa yang dilakukan kelas dasar? Nah, pertimbangkan skenario ini:
Yang kami inginkan adalah penulis D diberi tahu bahwa sesuatu yang relevan telah berubah . Hal yang relevan yang telah berubah adalah bahwa M sekarang merupakan persyaratan dan bahwa implementasinya harus kelebihan beban. DM mungkin perlu mengubah perilakunya setelah kita tahu bahwa itu bisa dipanggil dari kelas dasar. Hal yang benar untuk dilakukan adalah tidak diam-diam mengatakan "oh, DM ada dan memperluas BM". Hal yang benar untuk dilakukan oleh kompiler adalah gagal , dan katakan "hai, penulis D, lihat asumsi Anda yang tidak lagi valid dan perbaiki kode Anda jika perlu".
Dalam contoh Anda, anggap
override
saja opsional padaSayHello
karena itu menimpa metode abstrak. Ada dua kemungkinan: (1) pembuat kode bermaksud untuk menimpa metode abstrak, atau (2) metode utama diganti secara tidak sengaja karena orang lain mengubah kelas dasar, dan kode tersebut sekarang salah dalam beberapa cara yang halus. Kami tidak dapat membedakan kemungkinan ini jikaoverride
opsional .Tetapi jika
override
yang diperlukan maka kita dapat membedakan tiga skenario. Jika ada kesalahan mungkin dalam kode makaoverride
yang hilang . Jika sengaja utama kemudianoverride
adalah hadir . Dan jika sengaja tidak mengesampingkan kemudiannew
adalah hadir . Desain C # memungkinkan kita untuk membuat perbedaan yang halus ini.Ingat, pelaporan kesalahan kompiler memerlukan pembacaan pikiran pengembang ; kompiler harus menyimpulkan dari kode yang salah apa kode yang benar yang mungkin ada dalam pikiran penulis , dan memberikan kesalahan yang mengarahkan mereka ke arah yang benar. Semakin banyak petunjuk yang dapat membuat pengembang meninggalkan kode tentang apa yang mereka pikirkan, semakin baik pekerjaan yang dapat dilakukan oleh kompiler dalam melaporkan kesalahan dan karenanya semakin cepat Anda dapat menemukan dan memperbaiki bug Anda.
Tetapi lebih umum, C # dirancang untuk dunia di mana kode berubah . Banyak sekali fitur C # yang tampak "aneh" sebenarnya ada di sana karena mereka memberi tahu pengembang ketika asumsi yang dulu valid telah menjadi tidak valid karena kelas dasar berubah. Kelas bug ini disebut "kegagalan kelas dasar getas", dan C # memiliki sejumlah mitigasi yang menarik untuk kelas kegagalan ini.
sumber
Itu untuk menentukan apakah Anda mencoba menimpa metode lain di kelas induk atau membuat implementasi baru yang unik untuk tingkat hirarki kelas ini. Bisa dibayangkan bahwa seorang programmer mungkin tidak menyadari keberadaan metode di kelas induk dengan tanda tangan yang sama persis seperti yang mereka buat di kelas mereka, yang dapat menyebabkan beberapa kejutan yang tidak menyenangkan.
Meskipun benar bahwa metode abstrak harus ditimpa dalam kelas anak yang tidak abstrak, perajin C # mungkin merasa masih lebih baik untuk eksplisit tentang apa yang Anda coba lakukan.
sumber
Karena
abstract
metode adalah metode virtual tanpa implementasi, per spesifikasi bahasa C # , berarti bahwa metode abstrak secara implisit adalah metode virtual. Danoverride
digunakan untuk memperluas atau memodifikasi implementasi abstrak atau virtual, seperti yang Anda lihat di siniUntuk ulangi sedikit - Anda menggunakan metode virtual untuk mengimplementasikan beberapa jenis pengikatan akhir, sedangkan metode abstrak memaksa subkelas dari tipe tersebut agar metode tersebut diganti secara eksplisit. Itulah intinya, ketika metode itu
virtual
, itu bisa ditimpa, ketika itu adalahabstract
- itu harus digantisumber
Untuk menambahkan jawaban @ StriplingWarrior, saya pikir itu juga dilakukan untuk memiliki sintaks yang konsisten dengan mengesampingkan metode virtual di kelas dasar.
Jadi C # bisa dirancang sedemikian rupa sehingga Anda tidak perlu mengganti kata kunci untuk mengganti metode abstrak, tapi saya pikir para perancang memutuskan bahwa akan membingungkan karena tidak akan konsisten dengan mengganti metode virtual.
sumber
override
? Saya pikir kebanyakan orang akan setuju bahwa tidak masuk akal untuk memaksa penulis D untuk membuat perubahan kode yang tidak perlu; kelas mereka baik-baik saja!