我经常发现自己在处理类似于这个模式的问题。

两个继承树,其中有某种镜像。左侧树中的每个子类在右侧树中都有一个不同的子类作为source。
MappingEnd类:
public class MappingEnd
{
public NamedElement source { get; set; }
}问题是,如何在子类中处理这些问题。是否使用source关键字隐藏父new属性?
public class AssociationMappingEnd:MappingEnd
{
public new Association source { get; set; }
}还是我只是提供了第二个属性,将NamedElement转换为Association?
public class AssociationMappingEnd:MappingEnd
{
public Association associationSource
{
get
{
return (Association)this.source;
}
set
{
this.source = value;
}
}
}我为什么要选择一个而不是另一个。或者有更好的方法来实现这种类型的模式?
发布于 2018-09-26 19:13:06
在第一种设计中,public new Association source很容易造成麻烦。您仍然可以意外地访问隐藏成员public NamedElement source。这可不酷。
例如,看看这个伪代码:
IEnumerable<MappingEnd> MyMixedCollection = all kinds of MappingEnd objects
((AssociationMappingEnd)MyMixedCollection.First()).source //is cool
MyMixedCollection.First().source //access the hidden member, not coolnew关键字不是最佳的设计实践,因为它不隐藏继承的成员。它所做的基本上是隐藏没有它的警告信息。
我个人从来不认为这是一个有效的设计。
第二种设计更可靠,因为这些名字永远不会混淆。
AssociationMappingEnd.associationSource is Association
AssociationMappingEnd.source is NamedElement
MappingEnd.source is NamedElement但是,由于这些source和associationSource实际上是相同的,所以可能会引起混淆。它可以工作,但它可以更好。
我们不能在type-safety.上使用override并给它一种新的类型,我们可以使用public virtual NamedElement source,但是那样我们就会失去source为了保持类型安全,我们可以使用泛型,正如埃尔贡佐所建议的。
左侧需要是泛型的,因为它取决于其右侧类的类型,因此我们应该从左侧的顶级类开始:
public class MappingEnd<T> where T : NamedElement
{
public T source { get; set; }
}现在,您可以拥有这两个类中的一个或两个:
public class AssociationMappingEnd<T> : MappingEnd<T> where T : Association
{
}
public class AssociationMappingEnd : MappingEnd<Association>
{
}现在只有一个安全类型的source:
AssociationMappingEnd<Association>.source is Association
AssociationMappingEnd.source is Association
MappingEnd<NamedElement>.source is NamedElement
MappingEnd<Association>.source is Associationhttps://stackoverflow.com/questions/52425762
复制相似问题