在基类型中引用派生类型是不好的形式?

时间:2012-07-03 07:29:58

标签: c# oop inheritance

我有一个类别/文件树结构。类别和文件都可以包含父类,因此我从具有Parent属性的公共基类派生它们。由于所有父项显然都是类别(文件不能是父类),因此将节点的Parent属性设置为CategoryNode类似似乎是有意义的。

基类引用派生类是不好的形式?如果是这样,为什么?如果是这样的话,有什么更好的方法呢?

class Node {
    public CategoryNode Parent {get; set;}
}

class File : Node {
    ...
}

class CategoryNode : Node {
    ...
}

4 个答案:

答案 0 :(得分:7)

你可以......

interface IParent {
    ...
}

class Node {
    public IParent Parent {get; set;}
}

class File : Node {
    ...
}

class CategoryNode : Node, IParent {
    ...
}

这样,您不需要引用基类中的派生对象,而且,如果您在以后的某个时间点获得其他对象类型,则您在实际成为父对象时更灵活。 。此外,任何与父级相关的功能都可以在该接口中声明。

答案 1 :(得分:4)

如果属性Parent 实际上是所有后代的公共属性并且总是类型为CategoryNode,那么这不是问题。从语义上讲,这是正确的,从技术上来说,只要你保持在同一个库中,我认为它也是正确的(以避免循环引用)。

当您编写如下代码时,这可能是一个问题:

// BAD CODE
if(myProp is subclassA) 
{ ... 
} 
else if (myProp is syubclassB) 
{ ...
}

这段代码很糟糕,因为你失去了继承的优势。

即使在.Net Framework中也有这样的结构。我想到的第一个例子是XObject.Parent属性。

XElement继承XObject,XObject发布XElement类型的属性。与您的代码段相同。

答案 2 :(得分:1)

基类不应该知道是谁派生的。

如果你有这种情况,你可能不想继承。你应该使用某种形式的耦合。

File和CategoryNode应该包含您的案例中的Node成员。

答案 3 :(得分:1)

其他选项是更改类层次结构以使CategoryNode成为根类(a),或将属性类型更改为Node(b)。

这两种可能性都不好: (a)文件将具有它不需要的所有功能CategoryNode。 (b)它将隐藏对象类型(总是为CategoryNode)。这可能跟随代码中其他位置的无效转换错误。例如,如果您忘记了总是有一个CategoryNode实例。

考虑到这一点,我相信目前的代码还可以。