【发布时间】:2010-08-15 15:55:08
【问题描述】:
我有以下 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 { }
实现这一目标的最佳方法是什么?我想到了接口(@987654327@),但后来想到了(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: Kirk 关于实现接口的建议(以 Timwi 的代码为例)对我来说是不切实际的,因为每个类都有很多字段和方法(总共大约有 8 个类),所以我将不得不为每个“额外”派生组复制它们中的每一个。例如,这是 Node 类的外观:
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 is IExtraNode) == true。
-
@Kirk 感谢您的建议,但我需要的是 ExtraElement 作为 ExtraNode,而不是 IExtraNode。为了说明,我需要能够做到:ExtraNode = someExtraElement ??一些额外的节点。
-
对,所以如果您要实际使用接口,您可能希望正确且一致地使用它们。换句话说,您将不再希望声明 ExtraNode/ExtraElement/等。作为它们的具体类型——所有变量都将始终输入到接口中。然后,由于“ExtraNode”的类型为 IExtraNode,您可以这样做:ExtraNode = someExtraElement ??一些额外的节点。
-
@Kirk 但是接口与节点/元素/文档无关。他们只会有额外的东西。我当然需要对象同时具有来自 Node/Element/Document 和 Extra 的字段。
-
我不确定您是否可以控制 Node/Element/Document 类。如果你不这样做,你就不走运了。如果这样做,您应该创建这些类实现的 INode/IElement/IDocument 接口。然后您的“IExtra”版本将扩展这些基本接口。从那里你应该做生意。
标签: c# generics class interface multiple-inheritance