我经常发现自己正在处理与此相似的模式

c# - 处理镜像继承树-LMLPHP

两个继承树,其中存在某种镜像。左树中的每个子类在右树中都有一个不同的子类,即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;
        }
    }
}

我为什么要选择一个。还是有更好的方法来实现这种模式?

最佳答案

在第一种设计中,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 cool
new关键字不是最佳设计实践,因为它不会隐藏继承的成员。它所做的基本上是隐藏没有它的警告消息。

我个人从不认为这是有效的设计。

第二种设计更加可靠,因为这些名称永远不会混淆
AssociationMappingEnd.associationSource is Association
AssociationMappingEnd.source            is NamedElement

MappingEnd.source                       is NamedElement

但是,由于这些sourceassociationSource实际上是相同的,因此可能会造成混淆。它可以工作,但是可以更好。

我们不能在override上使用source并给它一个新的类型,我们可以使用public virtual NamedElement source,但是那样我们将失去类型安全。为了保持类型安全,我们可以使用泛型,如elgonzo建议的那样。

左侧需要通用,因为它取决于右侧类的类型,因此我们应该从左侧的顶级类开始:
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 Association

关于c# - 处理镜像继承树,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52425762/

10-16 10:28