Ortak bir alan ne zaman bir temel sınıfa taşınmalı?


16

Şu anda iki türetilmiş sınıf var Ave Bher ikisinin de ortak bir alanı var ve temel sınıfa girip girmeyeceğini belirlemeye çalışıyorum.

Asla temel sınıftan referans Calınmaz ve yolun bir noktasında başka bir sınıf türetilmişse , bunun bir sınıfına sahip değilse _field1, o zaman "en az ayrıcalıklı" (veya bir şey) ilkesinin ihlal edilmeyeceğini söyler oldu?

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
}

18
Bize ne bir fikrin vermediyseniz çünkü bu soru belirsiz olduğunu düşünüyorum Base, A, B, C, ve _field1vardır. Bunlar dışarıda bırakılmaması gereken önemli detaylardır; Sanırım bu soruların ne olduğu hakkında konuşmak için soruyu düzenlemelisiniz.
Tanner Swett

Cevaplara dayanarak: Sanal bir Süspansiyona sahip olmak için Aracı yeniden inşa ettikten sonra, Araba ve Bisikletin Tekerlekleri ve Teknesi, soyutlamayı yukarı doğru hareket ettirecek Yüzdürme'ye sahip olabilirdi. Eğer soyutlamam doğrudan belirli ayarlara götürürse, o zaman konsepti yeterince zincire taşımadığımı görüyorum.
Patrick Hughes

6
Kodu çoğaltmaktan kaçınmak için sınıf mirasını kullanmayın. Bunu, davranışı , yani polimorfizmi miras almak ve genişletmek için kullanın . Ortak bir alanı, yalnızca mantıksal olarak aynı alan ise, kendi bağlamlarında aynı adı paylaşan iki ilgisiz bilgi parçası değilse, bir temel sınıfa taşıyın .
Brandon

Neden başlangıçta bir temel sınıfınız var?
jpmc26

Yanıtlar:


34

Her şey çözmeye çalıştığınız soruna bağlıdır.

Somut bir örnek düşünün: soyut temel sınıfınız Vehicleve şu anda somut uygulamalarınız var Bicycleve Car. Sen hareketli düşünüyorsanız numberOfWheelsgelen Bicycleve Cararaca. Bunu yapmalı mısın? Hayır! Çünkü tüm araçların tekerlekleri yoktur. Bir Boatsınıf eklemeye çalışırsanız, o zaman kırılacağını söyleyebilirsiniz.

Eğer soyut temel sınıfınız şimdi üye değişkenine WheeledVehiclesahip olmak mantıklıdır numberOfWheels.

Probleminize aynı mantığı uygulamanız gerekir, çünkü gördüğünüz gibi bu basit bir evet veya hayır cevabı değildir.


3
Kişi geçici olarak 0'ın geçerli bir sayı olduğunu kabul edebilir. Bununla birlikte, sonunda roll(), alt sınıf fikrinin ileriye dönük göründüğü bir yöntem ekleyebilirsiniz .
user949300

11
Bir teknenin 0 tekerleği vardır. Bu ne kırıyor?
D Drmmr

14
@DDrmmr Bir Teknenin 0 tekerleği olmadığı için değil, Tekerlerin bir Tekne konsepti olarak bile mevcut olmadığı için modelleriniz buna izin vermemelidir.
Peter M

10
Demek istediğim, örnek kötü. Bir araçta (bu bir tekne olur) 0 tekerleği olduğunu belirten kavramsal olarak yanlış bir şey yoktur.
D Drmmr

10
Sonra bir kürek teknesi depolamak gerektiğinde her şey cehenneme gider.
IllusiveBrian

13

Mantıksal olarak konuşursak, alt sınıfta çoğaltılan alanı, temel sınıfta ortak yerine yerleştirmenin ötesinde, üçüncü bir seçenek vardır: bu, ikisi arasında ortak özelliklere sahip olan hiyerarşiye yeni bir alt sınıf eklemek. @Pete tam olarak oraya gitmeden ipuçları veriyor.

@ Pete örneğini kullanarak Tekerlekli Araç için orijinal taban sınıfından inen (muhtemelen soyut) bir alt sınıf tanıtacağız - iki alt sınıf da ondan aşağı iner. Bu nedenle, orijinal taban sınıfı tekerleklerle kirlenmez, ancak tekerleklerin ortaklığı DRY'dir (tekerlekleri olan alt sınıflar arasında tekrarlanmaz).

Bu, elbette, amaçlarınız için aşırıya kaçabilir, ancak bu, sınıf hiyerarşi mekanizması tarafından desteklenir.


Aslında yapmaya karar verdim (A ve B çoğunlukla örtüşüyor, bu yüzden B A'dan türetilecek).
samis

9

Burada şeytanın avukatını oynayacağım.

Şu an hiçbir şey yapmamalısın .

KURU mu? Hayır. Ancak, daha sonra kolayca geri dönemeyeceğiniz erken bir soyutlamadan küçük bir çoğaltma yapmak daha iyidir. Bir özelliği ortak bir temel sınıfa taşımak için refactor kolaydır. Diğer tarafa gitmek değil. Bekle ve gör.

Bu tür bir karar verirken "3 kuralı" kullanma eğilimindeyim: Aynı şeyi örneğin üç farklı yerde tekrarladıktan sonra ve ancak o zaman, onu zincirden yukarı çıkarmayı düşünebilir miyim. Not: Sadece 2 yaşındasın.


2
Karar vermek için akıllıca bir gözlem olduğunu söyleyebilirim.
radarbob

1
Çoğunlukla katılıyorum, ama "Şu anda" (gördüğümüz gibi hiçbir ekstra kod ile) her iki yönde yeniden düzenleme önemsiz. Ancak alanı kullanan ek kod varsa, her iki yönde yeniden düzenleme yapmak daha zor hale gelebilir.
Doc Brown

2

Genel olarak, onu temel sınıfa taşırdım. Nesnel bir evet / hayır olduğunu düşünmüyorum, çünkü burada bir denge var - kullanılmayan alanları taşımak ve karmaşıklığı azaltmak.

Genellikle paylaşılabilecek her şeyi içeren 'ağır' temel sınıfları tercih ederim. Bu, türetilmiş her sınıfta alt öğe serileştirme yöntemlerine ihtiyacınız olmadığından dosyalara serileştirmeyi kolaylaştırır. Ancak bu veya benzeri bir sorununuz yoksa veya belki de bellek kullanımını azaltmak için elinizden gelen her şeyi yapmanız gerekiyorsa, yalnızca ihtiyaç duyduğunuz alanları tutmak iyi olmalıdır.

Çok sınırlı sayıda alanınız varsa, ortak alanları tanıtan bir 'aracı' sınıf iyi olacaktır. Ancak, farklı kombinasyonlarda düzinelerce alanınız varsa, yaklaşımın karmaşıklığı önemli ölçüde artırabileceğini unutmayın; Bu bir bakım sorunu haline gelebilir.


Örneğim hala üretim kodu olmasına rağmen önemsiz. Hiyerarşiyi "ağır" bir temel sınıfla "tehlikeye atmak" için iyi bir argüman oluşturuyorsunuz.
samis

1
@ samis: "A, B, C" ve "Base" adlı sınıfları yalnızca bir alanla ve üretim kodunda yöntem kullanmadan mı kullanıyorsunuz? Bunu sorgularım.
Doc Brown
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.