Kapan harus memindahkan bidang umum ke kelas dasar?

16

Saat ini saya memiliki dua kelas turunan, Adan B, keduanya memiliki bidang yang sama dan saya mencoba untuk menentukan apakah harus naik ke kelas dasar.

Itu tidak pernah direferensikan dari kelas dasar, dan mengatakan jika di beberapa titik jalan kelas lain diturunkan C,, yang tidak memiliki _field1, maka tidak akan kepala sekolah "paling istimewa" (atau sesuatu) dilanggar jika dulu?

public abstract class Base
{
    // Should _field1 be brought up to Base?
    //protected int Field1 { get; set; }
}

public class A : Base
{
    private int _field1;
}

public class B : Base
{
    private int _field1;
}

public class C : Base
{
    // Doesn't have/reference _field1
}
Sam adalah
sumber
18
Saya pikir pertanyaan ini tidak jelas karena Anda belum memberi kita gagasan tentang apa Base, A, B, C, dan _field1adalah. Itu adalah detail penting yang tidak boleh diabaikan; Saya pikir Anda harus mengedit pertanyaan untuk berbicara tentang apa itu.
Tanner Swett
Berdasarkan jawaban saya akan: membangun kembali Kendaraan untuk memiliki Penangguhan virtual, maka Mobil dan Sepeda bisa memiliki Roda dan Perahu bisa memiliki Daya Apung, yang akan menggerakkan abstraksi ke atas. Saya menemukan bahwa jika abstraksi saya mengarah langsung ke pengaturan tertentu maka saya belum memindahkan konsep cukup jauh ke atas rantai.
Patrick Hughes
6
Jangan gunakan warisan kelas untuk menghindari duplikasi kode. Gunakan untuk mewarisi dan memperluas perilaku , yaitu polimorfisme. Pindahkan bidang umum ke kelas dasar jika dan hanya jika itu secara logis sama, bukan dua informasi yang tidak terkait yang kebetulan berbagi nama yang sama dalam konteksnya masing-masing.
Brandon
Mengapa Anda memiliki kelas dasar untuk memulai?
jpmc26

Jawaban:

34

Itu semua tergantung pada masalah yang Anda coba selesaikan.

Pertimbangkan contoh konkret: kelas dasar abstrak VehicleAnda dan Anda saat ini memiliki implementasi konkret Bicycledan Car. Anda sedang mempertimbangkan untuk pindah numberOfWheelsdari Bicycledan Carke kendaraan. Haruskah kamu melakukan ini? Tidak! Karena tidak semua kendaraan memiliki roda. Anda sudah bisa mengatakan bahwa jika Anda mencoba menambahkan Boatkelas maka itu akan rusak.

Sekarang, jika kelas dasar abstrak Anda WheeledVehiclemaka logis untuk memiliki numberOfWheelsvariabel anggota di sana.

Anda perlu menerapkan logika yang sama untuk masalah Anda, karena seperti yang Anda lihat, itu bukan jawaban ya atau tidak yang sederhana.

Pete
sumber
3
Seseorang dapat sementara menerima bahwa 0 adalah numberOfWheels yang valid. Namun, pada akhirnya Anda dapat menambahkan roll()metode, di mana ide subclass terlihat sudah bagus.
user949300
11
Sebuah perahu memiliki 0 roda. Apa yang pecah?
D Drmmr
14
@Drmmr Bukannya Perahu memiliki 0 roda, tetapi Roda bahkan tidak ada sebagai konsep untuk Perahu - maka model Anda seharusnya tidak mengizinkannya.
Peter M
10
Maksud saya adalah contohnya buruk. Tidak ada yang salah secara konsep dengan kendaraan (yang kebetulan adalah kapal) yang menyatakan bahwa ia memiliki 0 roda.
D Drmmr
10
Maka itu semua pergi ke neraka ketika Anda perlu menyimpan perahu dayung.
IllusiveBrian
13

Secara logis, selain menempatkan bidang yang direplikasi dalam subclass vs yang sama di kelas dasar, ada opsi ketiga: yaitu untuk memperkenalkan subclass baru ke dalam hierarki yang memiliki properti umum di antara keduanya. @Pete mengisyaratkan hal ini tanpa sepenuhnya pergi ke sana.

Menggunakan contoh @ Pete, kami akan memperkenalkan subkelas (mungkin abstrak) untuk Kendaraan Beroda yang diturunkan dari kelas dasar asli - sementara dua subkelas turun darinya. Dengan demikian, kelas dasar asli tidak tercemar dengan roda, namun kesamaan roda adalah KERING (tidak diulangi di antara subkelas yang memiliki roda).

Ini mungkin, tentu saja, berlebihan untuk tujuan Anda, tetapi itu didukung oleh mekanisme hierarki kelas.

Erik Eidt
sumber
Ini sebenarnya yang saya putuskan untuk lakukan (A dan B kebanyakan tumpang tindih, jadi B akan berasal dari A).
samis
9

Saya akan berperan sebagai penasihat iblis di sini.

Saat ini kamu seharusnya tidak melakukan apa - apa .

Apakah KERING? Tidak. Tetapi lebih baik memiliki duplikasi kecil daripada abstraksi prematur yang tidak bisa Anda tolak dengan mudah nanti. Refactor untuk memindahkan properti ke kelas dasar umum mudah. Pergi ke arah lain tidak. Tunggu dan lihat.

Ketika membuat keputusan semacam ini, saya cenderung menggunakan "aturan 3": begitu saya mengulangi hal yang sama di misalnya tiga tempat yang berbeda, dan hanya kemudian, saya mempertimbangkan untuk memindahkannya ke atas rantai. NB Anda hanya di 2.

Jared Smith
sumber
2
Pengamatan yang bijak, saya katakan, diperlukan untuk membuat keputusan.
radarbob
1
Saya sebagian besar setuju, tapi "Saat ini" (tanpa kode tambahan seperti yang kita lihat) refactoring di kedua arah sepele. Tetapi jika ada kode tambahan yang menggunakan bidang, refactoring di kedua arah bisa menjadi jauh lebih sulit.
Doc Brown
2

Secara umum, saya akan memindahkannya ke kelas dasar. Saya tidak berpikir ada tujuan ya / tidak, karena ada pertukaran di sini - membawa bidang yang tidak digunakan vs mengurangi kompleksitas.

Saya biasanya lebih suka kelas dasar 'berat' yang berisi apa pun yang mungkin dibagikan. Ini membuat serialisasi ke file lebih mudah karena Anda tidak perlu metode serialisasi turunan di setiap kelas turunan. Tetapi jika Anda tidak memiliki itu atau masalah serupa, atau mungkin Anda perlu melakukan semua yang Anda bisa untuk mengurangi penggunaan memori, maka hanya menjaga bidang di mana Anda membutuhkannya harus baik-baik saja.

Kelas 'perantara' yang memperkenalkan bidang umum akan baik-baik saja jika Anda memiliki jumlah bidang yang sangat terbatas. Namun ketahuilah bahwa pendekatan dapat secara dramatis meningkatkan kompleksitas jika Anda memiliki lusinan bidang yang digunakan dalam kombinasi yang berbeda, yang mengarah ke banyak kelas perantara yang masing-masing memperkenalkan kumpulan bidang tertentu. Itu bisa menjadi masalah pemeliharaan.

GrandmasterB
sumber
Contoh saya sepele, meskipun masih kode produksi. Anda membuat argumen yang bagus untuk "mengkompromikan" hierarki dengan kelas dasar "berat", yang saya juga akan melihat diri saya condong ke arah dalam kasus seperti itu.
samis
1
@samis: Anda menggunakan kelas bernama "A, B, C" dan "Basis" hanya dengan satu bidang dan tidak ada metode dalam kode produksi? Saya mempertanyakan itu.
Doc Brown