我有一个类别/文件树结构。类别和文件都可以包含父类,因此我从具有Parent属性的公共基类派生它们。由于所有父项显然都是类别(文件不能是父类),因此将节点的Parent属性设置为CategoryNode类似似乎是有意义的。
基类引用派生类是不好的形式?如果是这样,为什么?如果是这样的话,有什么更好的方法呢?
class Node {
public CategoryNode Parent {get; set;}
}
class File : Node {
...
}
class CategoryNode : Node {
...
}
答案 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实例。
考虑到这一点,我相信目前的代码还可以。