简体   繁体   English

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

[英]Is it bad form to refer to a derived type in a base type?

I have a category/file tree structure. 我有一个类别/文件树结构。 Both categories and files can have parents, so I derived them from a common base class that has a Parent property. 类别和文件都可以包含父类,因此我从具有Parent属性的公共基类派生它们。 Since all parents will obviously always be categories (files can't be a parent), it seems to make sense to make the Parent property of the node be the CategoryNode type. 由于所有父项显然都是类别(文件不能是父类),因此将节点的Parent属性设置为CategoryNode类似似乎是有意义的。

Is it bad form for the base class to refer to the derived class? 基类引用派生类是不好的形式? If so, why? 如果是这样,为什么? What's a better way to structure this, if so? 如果是这样的话,有什么更好的方法呢?

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

class File : Node {
    ...
}

class CategoryNode : Node {
    ...
}

You could do ... 你可以......

interface IParent {
    ...
}

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

class File : Node {
    ...
}

class CategoryNode : Node, IParent {
    ...
}

This way, you don't need to refer to a derived object in the base class, plus, you're more flexible in what can actually become a parent, in case you get additional object types at a later point in time. 这样,您就不需要在基类中引用派生对象,而且,如果您在以后获得其他对象类型,则您可以更灵活地实际成为父对象。 Also, any functionality that is relevant just for a parent can be declared in that interface. 此外,可以在该接口中声明与父级相关的任何功能。

If the property Parent is actually a common properties of all descendants and always of kind CategoryNode, it's not a problem. 如果属性Parent 实际上是所有后代的公共属性,并且总是类型为CategoryNode,那么这不是问题。 Semantically speaking it's correct and technically I think its correct too as soon as you remain in the same library (to avoid circular references). 从语义上讲,这是正确的,从技术上来说,只要你保持在同一个库中,我认为它也是正确的(避免循环引用)。

This can be a problem when you write code like this : 当您编写如下代码时,这可能是一个问题:

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

This code is bad, because you loose the advantage of inheritance. 这段代码很糟糕,因为你失去了继承的优势。

Even in the .Net Framework there is such constructs . 即使在.Net Framework中也存在这样的结构 The first example that comes in my mind is the XObject.Parent property. 我想到的第一个例子是XObject.Parent属性。

XElement inherits XObject, and XObject publish a property of type XElement. XElement继承XObject,XObject发布XElement类型的属性。 Same as your snippet. 与您的代码段相同。

The base class shouldn't know who derives from it. 基类不应该知道是谁派生的。

If you have such a case, you probably dont want inheritance. 如果你有这种情况,你可能不想要继承。 You should just use some form of coupling. 你应该使用某种形式的耦合。

The File and CategoryNode should hold a Node member in your case. File和CategoryNode应该包含您的案例中的Node成员。

Other options will be to change class hierarchy to make the CategoryNode a root class (a), or change the property type to Node (b). 其他选项是更改类层次结构以使CategoryNode成为根类(a),或将属性类型更改为Node(b)。

Both of these possibilities are not good: (a) File will have all functionality CategoryNode has which it doesn't need. 这两种可能性都不好:(a)文件将具有它不需要的所有功能CategoryNode。 (b) It will hide object type (which is always CategoryNode). (b)它将隐藏对象类型(总是为CategoryNode)。 This may follow to invalid cast errors somewhere else in your code. 这可能跟随代码中其他位置的无效转换错误。 For example, if you forget there is always a CategoryNode instance. 例如,如果您忘记了总是有一个CategoryNode实例。

Considering this, I believe current code is OK. 考虑到这一点,我相信当前的代码是可以的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM