我有以下3类:类派生问题
class Node {
public Node Parent;
// Edit: to clarify, each of these classes has many fields and methods
public void Method1() { /*...*/ }
public void Method2() { /*...*/ }
/* ... */
public void Method30() { /*...*/ }
}
class Element : Node { public Dictionary<string, string> Attributes; }
class Document : Element { }
我需要有一种方法来定义ExtraNode
,ExtraElement
和ExtraDocument
让他们复制上面的代码,添加了一些额外的字段的等效到Node
类,并用前缀“额外”的所有类,像这样:
class ExtraNode { public Node Parent; public int Priority; }
class ExtraElement : ExtraNode { public Dictionary<string, string> Attributes; }
class ExtraDocument : ExtraElement { }
什么是最好的,以实现这一目标?我想过接口(ExtraNode : Node, IExtra
),但接着是(ExtraElement is ExtraNode) == false
。
我也想过重写类作为泛型(Node<T>, Element<T>, Document<T>
),然后用它们来定义新的类(ExtraNode : Node<MyExtraClass>
等),但它仍然导致了(ExtraElement is ExtraNode) == false
因为(Element<MyExtraClass> is Node<MyExtraClass>) == false
问题。
那么实现这一目标的最佳方法是什么,而不需要复制/粘贴整个文档并手动更改?我需要不止一次地这样做。
编辑:澄清什么,我需要能够做的,我需要下面的代码工作:
// this should accept an ExtraNode, an ExtraElement or an ExtraDocument:
void doSomethingWithANode(ExtraNode extraNode) { ... }
编辑2:柯克的有关实现接口(通过Timwi的代码作为例证的建议)在我的情况下是不切实际的,因为每个类都有很多字段和方法(总共大约有8个类),所以我必须为每个“Extra”派生组复制其中的每一个。例如,这是节点类的外观:
class INode {
INode Parent { get; }
void Method1();
void Method2();
/* ... */
void Method30();
}
class ExtraNode {
public int Priority { get; } // extra
public INode Parent { get; } // THIS IS WRONG, THIS SHOULD BE ExtraNode NOT INode
public void Method1() { ... } // here I have to define the entire method
public void Method2() { ... }
/* ... */
public void Method30() { ... }
}
class SuperNode {
public string Superpower { get; } // extra
public INode Parent { get; } // THIS IS WRONG, THIS SHOULD BE SuperNode NOT INode
public void Method1() { ... } // here I have to define the entire method AGAIN
public void Method2() { ... } // all methods are identical to the ones in ExtraNode
/* ... */
public void Method30() { ... } // this is unnecessary code duplication
}
所以30个方法每次都重复一次。这适用于所有其他类。通过这种方法,我会重复这么多,我实际上复制了所有的代码。简单地复制/粘贴整个课程,重命名并添加额外的字段会更容易。
如果您使用的是接口,那么您大概会拥有IExtraNode,IExtraElement和IExtraDocument。 ExtraElement将被定义为ExtraElement:Element,IExtraElement和IExtraElement将被定义为IExtraElement:IExtraNode。通过这个设置,(ExtraElement是IExtraNode)== true。 – 2010-08-15 16:05:39
@Kirk感谢您的建议,但我需要ExtraElement作为ExtraNode,而不是IExtraNode。为了说明,我需要能够做到:ExtraNode = someExtraElement? someExtraNode。 – manixrock 2010-08-15 17:21:10
对,所以如果你真的要使用接口,你可能想要正确和一致地使用它们。换句话说,你不会再声明ExtraNode/ExtraElement/etc。作为它们的具体类型 - 您的所有变量将始终输入到界面中。然后,由于“ExtraNode”将是IExtraNode类型,因此您可以这样做:ExtraNode = someExtraElement ?? someExtraNode。 – 2010-08-15 17:30:33