Saya memiliki kelas dasar abstrak dan saya ingin mendeklarasikan bidang atau properti yang akan memiliki nilai berbeda di setiap kelas yang diwarisi dari kelas induk ini.
Saya ingin mendefinisikannya dalam baseclass sehingga saya dapat merujuknya dalam metode kelas dasar - misalnya menimpa ToString untuk mengatakan "Objek ini adalah tipe properti / bidang ". Saya punya tiga cara yang bisa saya lihat untuk melakukan ini, tetapi saya bertanya-tanya - apa cara terbaik atau diterima untuk melakukan ini? Pertanyaan pemula, maaf.
Opsi 1:
Gunakan Properti abstrak dan menimpanya di kelas yang diwarisi. Ini manfaat dari ditegakkan (Anda harus menimpanya) dan bersih. Tapi, rasanya sedikit salah untuk mengembalikan nilai kode keras daripada merangkum bidang dan itu adalah beberapa baris kode, bukan hanya. Saya juga harus mendeklarasikan badan untuk "mengatur" tetapi itu kurang penting (dan mungkin ada cara untuk menghindari apa yang saya tidak sadari).
abstract class Father
{
abstract public int MyInt { get; set;}
}
class Son : Father
{
public override int MyInt
{
get { return 1; }
set { }
}
}
Opsi 2
Saya bisa mendeklarasikan bidang publik (atau bidang yang dilindungi) dan secara eksplisit menimpanya di kelas yang diwarisi. Contoh di bawah ini akan memberi saya peringatan untuk menggunakan "baru" dan saya mungkin bisa melakukan itu, tetapi rasanya salah dan itu merusak polimorfisme, yang merupakan intinya. Sepertinya bukan ide yang bagus ...
abstract class Mother
{
public int MyInt = 0;
}
class Daughter : Mother
{
public int MyInt = 1;
}
Opsi 3
Saya bisa menggunakan bidang yang dilindungi dan menetapkan nilai dalam konstruktor. Ini tampaknya cukup rapi tetapi bergantung pada saya untuk memastikan konstruktor selalu menetapkan ini dan dengan beberapa konstruktor kelebihan beban selalu ada kesempatan beberapa jalur kode tidak akan menetapkan nilai.
abstract class Aunt
{
protected int MyInt;
}
class Niece : Aunt
{
public Niece()
{
MyInt = 1;
}
}
Ini sedikit pertanyaan teoretis dan saya kira jawabannya harus menjadi opsi 1 karena ini adalah satu-satunya pilihan yang aman, tetapi saya hanya ingin memahami C # dan ingin menanyakan hal ini kepada orang-orang dengan pengalaman lebih.
sumber
Jawaban:
Dari tiga solusi, hanya Opsi 1 yang polimorfik .
Fields sendiri tidak bisa diganti. Itulah sebabnya Opsi 2 mengembalikan peringatan kata kunci baru .
Solusi untuk peringatan ini bukan untuk menambahkan kata kunci "baru", tetapi untuk mengimplementasikan Opsi 1.
Jika Anda perlu bidang Anda menjadi polimorfik, Anda harus membungkusnya dalam Properti.
Opsi 3 OK jika Anda tidak memerlukan perilaku polimorfik. Anda harus ingat, bahwa ketika runtime properti MyInt diakses, kelas turunan tidak memiliki kontrol pada nilai yang dikembalikan. Kelas dasar dengan sendirinya mampu mengembalikan nilai ini.
Ini adalah bagaimana implementasi yang benar-benar polimorfik dari properti Anda terlihat, memungkinkan kelas turunan untuk memegang kendali .
sumber
Opsi 2 adalah non-starter - Anda tidak bisa menimpa bidang, Anda hanya bisa menyembunyikannya .
Secara pribadi, saya akan memilih opsi 1 setiap kali. Saya mencoba untuk menjaga bidang pribadi setiap saat. Itu jika Anda benar-benar harus dapat menimpa properti sama sekali, tentu saja. Opsi lain adalah memiliki properti read-only di kelas dasar yang ditetapkan dari parameter konstruktor:
Itu mungkin pendekatan yang paling tepat jika nilainya tidak berubah selama masa contoh.
sumber
opsi 2 adalah ide yang buruk. Ini akan menghasilkan sesuatu yang disebut membayangi; Pada dasarnya Anda memiliki dua anggota "MyInt" yang berbeda, satu di ibu, dan yang lainnya di putri. Masalah dengan ini, adalah bahwa metode yang diterapkan pada ibu akan referensi ibu "MyInt" sementara metode yang diterapkan pada anak perempuan akan referensi anak perempuan "MyInt". ini dapat menyebabkan beberapa masalah keterbacaan serius, dan kebingungan di kemudian hari.
Secara pribadi, saya pikir pilihan terbaik adalah 3; karena memberikan nilai terpusat yang jelas, dan dapat dirujuk secara internal oleh anak-anak tanpa perlu mendefinisikan bidang mereka sendiri - yang merupakan masalah dengan opsi 1.
sumber
Anda bisa melakukan ini
virtual memungkinkan Anda mendapatkan properti benda yang melakukan sesuatu dan masih membiarkan sub-kelas menimpanya.
sumber
Anda dapat mendefinisikan sesuatu seperti ini:
Dengan menetapkan nilai sebagai hanya baca, itu memastikan bahwa nilai untuk kelas itu tetap tidak berubah selama masa objek.
Saya kira pertanyaan selanjutnya adalah: mengapa Anda membutuhkannya?
sumber
Jika Anda sedang membangun kelas dan Anda ingin ada nilai dasar untuk properti, maka gunakan
virtual
kata kunci di kelas dasar. Ini memungkinkan Anda untuk mengganti properti secara opsional.Menggunakan contoh Anda di atas:
Dalam sebuah program:
sumber
Saya akan menggunakan opsi 3, tetapi memiliki metode setMyInt abstrak yang dipaksa untuk diimplementasikan oleh subclass. Dengan cara ini Anda tidak akan memiliki masalah kelas turunan lupa untuk mengaturnya di konstruktor.
By the way, dengan opsi satu, jika Anda tidak menentukan set; di properti kelas dasar abstrak Anda, kelas turunan tidak perlu mengimplementasikannya.
sumber
Anda bisa pergi dengan opsi 3 jika Anda memodifikasi kelas dasar abstrak Anda untuk memerlukan nilai properti di konstruktor, Anda tidak akan kehilangan jalur apa pun. Saya benar-benar mempertimbangkan opsi ini.
Tentu saja, Anda kemudian masih memiliki opsi untuk menjadikan bidang tersebut pribadi dan kemudian, tergantung pada kebutuhan, mengungkap pembuat properti yang dilindungi atau properti publik.
sumber
Saya melakukan ini ...
Dengan cara ini Anda masih bisa menggunakan bidang.
sumber
Contoh implementasi ketika Anda ingin memiliki kelas abstrak dengan implementasi. Subkelas harus:
Dalam hal ini, properti yang diperlukan untuk implementasi seharusnya tidak tersedia untuk digunakan kecuali untuk kelas abstrak dan subkelasnya sendiri.
sumber