// Cannot change source code
class Base
{
public virtual void Say()
{
Console.WriteLine("Called from Base.");
}
}
// Cannot change source code
class Derived : Base
{
public override void Say()
{
Console.WriteLine("Called from Derived.");
base.Say();
}
}
class SpecialDerived : Derived
{
public override void Say()
{
Console.WriteLine("Called from Special Derived.");
base.Say();
}
}
class Program
{
static void Main(string[] args)
{
SpecialDerived sd = new SpecialDerived();
sd.Say();
}
}
Hasilnya adalah:
Dipanggil dari Special Derived.
Dipanggil dari Berasal. / * ini tidak diharapkan * /
Dipanggil dari Base.
Bagaimana saya bisa menulis ulang kelas SpecialDerived sehingga metode kelas menengah "Derived" tidak dipanggil?
UPDATE:
Alasan mengapa saya ingin mewarisi dari Derived bukannya Base is Derived class berisi banyak implementasi lainnya. Karena saya tidak bisa melakukannya di base.base.method()
sini, saya rasa cara terbaik adalah melakukan hal berikut?
// Tidak dapat mengubah kode sumber
class Derived : Base
{
public override void Say()
{
CustomSay();
base.Say();
}
protected virtual void CustomSay()
{
Console.WriteLine("Called from Derived.");
}
}
class SpecialDerived : Derived
{
/*
public override void Say()
{
Console.WriteLine("Called from Special Derived.");
base.Say();
}
*/
protected override void CustomSay()
{
Console.WriteLine("Called from Special Derived.");
}
}
c#
polymorphism
AZ.
sumber
sumber
Jawaban:
Hanya ingin menambahkan ini di sini, karena orang masih kembali ke pertanyaan ini bahkan setelah sekian waktu. Tentu saja ini praktik yang buruk, tetapi masih mungkin (pada prinsipnya) untuk melakukan apa yang diinginkan penulis dengan:
sumber
Func<stuff>
alih-alihAction
Ini adalah praktik pemrograman yang buruk, dan tidak diperbolehkan di C #. Ini praktik pemrograman yang buruk karena
Detail dari grandbase adalah detail implementasi dari base; Anda seharusnya tidak bergantung pada mereka. Kelas dasar menyediakan abstraksi di atas grandbase; Anda harus menggunakan abstraksi itu, bukan membuat jalan pintas untuk menghindarinya.
Untuk mengilustrasikan contoh spesifik dari poin sebelumnya: jika diizinkan, pola ini akan menjadi cara lain untuk membuat kode rentan terhadap kegagalan kelas-basis-rapuh. Misalkan
C
berasal dariB
yang berasalA
. KodeC
digunakanbase.base
untuk memanggil metodeA
. Kemudian penulisB
menyadari bahwa mereka telah menempatkan terlalu banyak peralatan di kelasB
, dan pendekatan yang lebih baik adalah membuat kelas menengahB2
yang berasal dariA
, danB
dariB2
. Setelah perubahan itu, code inC
memanggil metode inB2
, bukan inA
, karenaC
penulis berasumsi bahwa detail implementasi dariB
, yaitu kelas basis langsungnya adalahA
, tidak akan pernah berubah. Banyak keputusan desain di C # adalah untuk mengurangi kemungkinan berbagai jenis kegagalan dasar yang rapuh; keputusan untuk membuatbase.base
ilegal sepenuhnya mencegah rasa khusus dari pola kegagalan itu.Anda berasal dari basis Anda karena Anda menyukai apa yang dilakukannya dan ingin menggunakan kembali serta memperluasnya. Jika Anda tidak menyukai apa yang dilakukannya dan ingin mengatasinya daripada mengerjakannya, lalu mengapa Anda berasal darinya? Dapatkan dari grandbase sendiri jika itu adalah fungsionalitas yang ingin Anda gunakan dan kembangkan.
Basis mungkin memerlukan invarian tertentu untuk tujuan keamanan atau konsistensi semantik yang dipertahankan oleh detail tentang bagaimana basis menggunakan metode grandbase. Mengizinkan kelas turunan dari basis untuk melewati kode yang mempertahankan invarian tersebut dapat membuat basis menjadi tidak konsisten, keadaan rusak.
sumber
Anda tidak bisa dari C #. Dari IL, ini sebenarnya didukung. Anda dapat melakukan panggilan non-virt ke salah satu kelas orang tua Anda ... tapi tolong jangan. :)
sumber
Jawabannya (yang saya tahu bukan yang Anda cari) adalah:
Sebenarnya, Anda hanya memiliki interaksi langsung dengan kelas yang Anda warisi. Pikirkan kelas itu sebagai lapisan - menyediakan sebanyak atau sesedikit itu atau fungsionalitas induknya seperti yang diinginkannya ke kelas turunannya.
EDIT:
Pengeditan Anda berfungsi, tetapi saya pikir saya akan menggunakan sesuatu seperti ini:
Tentu saja, dalam implementasi nyata, Anda mungkin melakukan sesuatu yang lebih seperti ini untuk ekstensibilitas dan pemeliharaan:
Kemudian, kelas turunan dapat mengontrol keadaan orang tuanya dengan tepat.
sumber
Derived
mana panggilanBase.Say
, sehingga dapat dipanggilSpecialDerived
? Lebih sederhana, bukan?Mengapa tidak melemparkan kelas anak ke kelas induk tertentu dan meminta implementasi spesifik itu? Ini adalah situasi kasus khusus dan solusi kasus khusus harus digunakan. Anda harus menggunakan
new
kata kunci dalam metode anak-anak.sumber
sumber
Anda juga dapat membuat fungsi sederhana di kelas turunan tingkat pertama, untuk memanggil fungsi grand base
sumber
2c saya untuk ini adalah untuk mengimplementasikan fungsionalitas yang Anda perlukan untuk dipanggil dalam kelas toolkit dan memanggilnya dari mana pun Anda membutuhkan:
Ini memerlukan pemikiran untuk mengakses hak istimewa, Anda mungkin perlu menambahkan beberapa
internal
metode pengakses untuk memfasilitasi fungsionalitas tersebut.sumber
Dalam kasus di mana Anda tidak memiliki akses ke sumber kelas turunan, tetapi membutuhkan semua sumber kelas turunan selain metode saat ini, maka saya akan merekomendasikan Anda juga harus melakukan kelas turunan dan memanggil implementasi kelas turunan.
Berikut ini contohnya:
sumber
Seperti yang dapat dilihat dari posting sebelumnya, seseorang dapat berargumen bahwa jika fungsionalitas kelas perlu dielakkan maka ada sesuatu yang salah dalam arsitektur kelas. Itu mungkin benar, tetapi seseorang tidak selalu dapat merestrukturisasi atau memfaktor ulang struktur kelas pada proyek besar yang matang. Berbagai tingkat manajemen perubahan mungkin menjadi satu masalah, tetapi untuk menjaga fungsionalitas yang ada tetap beroperasi sama setelah pemfaktoran ulang tidak selalu merupakan tugas yang sepele, terutama jika batasan waktu berlaku. Pada proyek yang matang, dapat menjadi usaha yang cukup berat untuk menjaga berbagai uji regresi agar tidak lolos setelah restrukturisasi kode; sering ada "keanehan" yang muncul. Kami memiliki masalah serupa dalam beberapa kasus, fungsi yang diwariskan tidak boleh dijalankan (atau harus melakukan sesuatu yang lain). Pendekatan yang kami ikuti di bawah ini, adalah meletakkan kode dasar yang perlu dikecualikan dalam fungsi virtual terpisah. Fungsi ini kemudian dapat diganti di kelas turunan dan fungsionalitasnya dikecualikan atau diubah. Dalam contoh ini "Teks 2" dapat dicegah dari keluaran di kelas turunan.
sumber
Tampaknya ada banyak pertanyaan seputar mewarisi metode anggota dari Kelas Kakek, menimpanya di Kelas kedua, lalu memanggil metode itu lagi dari Kelas Cucu. Mengapa tidak mewarisi anggota dari kakek nenek sampai ke cucu?
Sepertinya sederhana .... cucu mewarisi metode kakek-nenek di sini. Pikirkan tentang itu ..... begitulah "Object" dan anggotanya seperti ToString () diwarisi ke semua kelas di C #. Saya pikir Microsoft belum melakukan pekerjaan yang baik dalam menjelaskan warisan dasar. Terlalu banyak fokus pada polimorfisme dan implementasi. Ketika saya menggali dokumentasi mereka, tidak ada contoh dari ide yang sangat mendasar ini. :(
sumber
Jika Anda ingin mengakses data kelas dasar Anda harus menggunakan kata kunci "ini" atau Anda menggunakan kata kunci ini sebagai referensi untuk kelas.
sumber