Benim için bu, genel NamedEntity'ye güvenmek yerine sınıfa somut bir isim vermesi anlamlıdır. Öte yandan, ek bir özelliği olmayan birtakım sınıflar vardır.
Bu yaklaşımın herhangi bir dezavantajı var mı?
Yaklaşım fena değil, ancak daha iyi çözümler mevcut. Kısacası, bir arayüz bunun için çok daha iyi bir çözüm olacaktır. Arayüzlerin ve kalıtımın farklı olmasının temel nedeni , yalnızca bir sınıftan miras alabilmeniz, ancak birçok arayüzü uygulayabilmenizdir .
Örneğin, varlıklar ve denetlenmiş varlıklar olduğunuzu düşünün. Birkaç varlığınız var:
One
denetlenmiş bir varlık veya adlandırılmış bir varlık değildir. Bu basit:
public class One
{ }
Two
adlandırılmış bir varlıktır ancak denetlenmiş bir varlık değildir. Esasen şu an sahip olduğunuz şey bu:
public class NamedEntity
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Two : NamedEntity
{ }
Three
hem adlandırılmış hem de denetlenmiş bir girdidir. Bir problemin olduğu yer burası. Bir AuditedEntity
temel sınıf oluşturabilirsiniz , ancak ikisini deThree
devralamazsınız ve : AuditedEntity
NamedEntity
public class AuditedEntity
{
public DateTime CreatedOn { get; set; }
public DateTime UpdatedOn { get; set; }
}
public class Three : NamedEntity, AuditedEntity // <-- Compiler error!
{ }
Ancak, AuditedEntity
miras alarak bir geçici çözüm düşünebilirsiniz NamedEntity
. Bu, her bir sınıfın yalnızca (doğrudan) başka bir sınıftan miras alması gerektiğinden emin olmak için akıllıca bir keskidir.
public class AuditedEntity : NamedEntity
{
public DateTime CreatedOn { get; set; }
public DateTime UpdatedOn { get; set; }
}
public class Three : AuditedEntity
{ }
Bu hala çalışıyor. Ancak burada yaptığınız, denetlenen her bir varlığın doğal olarak aynı zamanda bir adlandırılmış varlık olduğu belirtilmektedir . Bu beni son örneğime getiriyor. Four
denetlenmiş bir varlıktır ancak adlandırılmış bir varlık değildir Ama izin veremem Four
gelen devralır AuditedEntity
sonra da bir yapım olacağını olarak NamedEntity
AuditedEntity arasındaki miras nedeniyle and
NamedEntity`.
Kalıtım kullanarak, her ikisini de yapmanın Three
ve Four
dersleri çoğaltmaya başlamadıkça (bu, tamamen yeni bir sorun kümesi açar) çalışmaz.
Arabirimleri kullanarak, bu kolayca elde edilebilir:
public interface INamedEntity
{
int Id { get; set; }
string Name { get; set; }
}
public interface IAuditedEntity
{
DateTime CreatedOn { get; set; }
DateTime UpdatedOn { get; set; }
}
public class One
{ }
public class Two : INamedEntity
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Three : INamedEntity, IAuditedEntity
{
public int Id { get; set; }
public string Name { get; set; }
DateTime CreatedOn { get; set; }
DateTime UpdatedOn { get; set; }
}
public class Four : IAuditedEntity
{
DateTime CreatedOn { get; set; }
DateTime UpdatedOn { get; set; }
}
Buradaki tek küçük dezavantajı, hala arayüzü uygulamak zorunda olmasıdır. Ancak, belirli bir varlık için birden fazla ortak türde değişiklik yapılması gerektiğinde ortaya çıkan dezavantajları olmadan, ortak bir yeniden kullanılabilir tipe sahip olmanın tüm faydalarını elde edersiniz.
Fakat polimorfizminiz bozulmadan kaldı:
var one = new One();
var two = new Two();
var three = new Three();
var four = new Four();
public void HandleNamedEntity(INamedEntity namedEntity) {}
public void HandleAuditedEntity(IAuditedEntity auditedEntity) {}
HandleNamedEntity(one); //Error - not a named entity
HandleNamedEntity(two);
HandleNamedEntity(three);
HandleNamedEntity(four); //Error - not a named entity
HandleAuditedEntity(one); //Error - not an audited entity
HandleAuditedEntity(two); //Error - not an audited entity
HandleAuditedEntity(three);
HandleAuditedEntity(four);
Öte yandan, ek bir özelliği olmayan birtakım sınıflar vardır.
Bu, sadece belirli bir sınıfın bu arayüzle "işaretlenmiş" olup olmadığını kontrol etmek için arayüz tipini kullanabilmek için sadece arayüz arayüzünü kullanabilmek için boş bir arayüz uyguladığınız marker arayüz modelinde bir varyasyondur .
Uygulanan arabirimler yerine kalıtsal sınıfları kullanıyorsunuz, ancak amaç aynı, bu yüzden "işaretli bir sınıf" olarak bahsedeceğim.
Yüz değerinde, işaretleyici arabirimleri / sınıflarında yanlış bir şey yoktur. Sözdizimsel ve teknik olarak geçerlidirler ve işaretleyicinin evrensel olarak doğru olması (derleme zamanında) ve koşullu olmaması şartıyla bunları kullanmanın sakıncaları yoktur .
Bu tam olarak, istisnalar arasında, temel istisna ile karşılaştırıldığında herhangi bir ek özellik / yöntem olmasa bile, farklı istisnalar arasında nasıl ayrım yapmanız gerektiğidir.
Yani bunu yaparken doğal olarak yanlış bir şey yok, ama sadece temkinli bir şekilde, kötü tasarlanmış polimorfizmle var olan bir mimari hatayı örtbas etmeye çalışmadığınızdan emin olmanızı öneririm.
OrderDateInfo
s ile ilgili olan yöntemleri diğerNamedEntity
s ile ilgili olanlardan