I have the following 3 classes:
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 { }
I need to have a way to define ExtraNode
, ExtraElement
and ExtraDocument
so that they are the equivalent of copying the code above, adding a few extra fields to the Node
class, and prefixing all classes with "Extra", like so:
class ExtraNode { public Node Parent; public int Priority; }
class ExtraElement : ExtraNode { public Dictionary<string, string> Attributes; }
class ExtraDocument : ExtraElement { }
What is the best to achieve this? I thought about interfaces (ExtraNode : Node, IExtra
), but then (ExtraElement is ExtraNode) == false
.
I also thought about rewriting the classes as generics (Node<T>, Element<T>, Document<T>
), then using them to define the new classes (ExtraNode : Node<MyExtraClass>
and so on), but it still leads to the problem of (ExtraElement is ExtraNode) == false
because (Element<MyExtraClass> is Node<MyExtraClass>) == false
.
So what is the best way of achieving this, without copy / pasting the entire document and changing by hand? I will need to do this more than once.
Edit: to clarify what I need to be able to do, I need the following code to work:
// this should accept an ExtraNode, an ExtraElement or an ExtraDocument:
void doSomethingWithANode(ExtraNode extraNode) { ... }
Edit 2: Kirk's suggestion about implementing interfaces (as exemplified by Timwi's code) is impractical in my case because each class has many fields and methods (and there are about 8 classes in total), so I would have to copy each and every one of them for each 'Extra' derivate group. For example this is how the Node classes would look:
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
}
So 30 methods are duplicated every single time. And this applies for all the other classes. By this method I would duplicate so much, I'm practically duplicating all the code. It would be easier to simply copy / paste the entire class, rename and add the extra fields to them.