0

I have a problem with Classes and Interfaces. I want to achive that an Interface declaretes a method that takes the type of the implemented class. When I inherit from this class the method should only take the type of the inherited class.

Is this possible?

A short code snipped:

class Program
{
    static void Main(string[] args)
    {
        Node node1 = new Node();
        Node node2 = new Node();
        Node node3 = new Node();

        // Connect node2 to node1 and node3 to node1.
        node1.connect(node2)
             .connect(node3);

        SomeNode node4 = new SomeNode();
        SomeNode node5 = new SomeNode();

        node4.connect(node5);

        // node1.connect(node4); // This should not be possible because node1.connect() should only accept Node and not SomeNode.
    }
}

interface INode
{
    int Id { get; set; }

    // Instead of INode, here should be the type of the implementing class or the type of the subclass (or the sub-subclass ...).
    INode connect(INode node); 
}

class Node : INode
{
    public int Id { get; set; }

    // This list MUST be protected and MUST be able to contain only objects of the current class type.
    protected List<Node> connectedNodes; 

    // This should implement the interface mehtod but in subclasses, the type should not be Node but the type of the subclass.
    // Of cause, this method should not be reimplemented in subclasses.
    public Node connect(Node node)
    {
        this.connectedNodes.Add(node);

        return this; // Enable chaining.
    }
}

class SomeNode : Node
{
    // Here should be some additional functionality but NOT the connect() method!
}
x3ro
  • 329
  • 1
  • 5
  • 11
  • If its possible, its probably ugly. For example, you could throw an exception if node isnt a node. But that gives runtime and not compile time checking. – D. Ben Knoble Sep 04 '15 at 02:49

1 Answers1

0

You can get basically what you describe by making INode generic on the node type and using a generic base class for your node's. The generic node type will be used to allow a single implementation to use different types

interface INode<TNode> {
    int Id { get; set; }
    TNode connect(TNode node); 
}

abstract class NodeBase<TNode> : INode<TNode> {
    public int Id { get; set; }
    protected List<TNode> connectedNodes; 

    public TNode connect(TNode node) {
        this.connectedNodes.Add(node);
        return this; // Enable chaining.
    }
}

class Node : NodeBase<Node> { }

class SomeNode : NodeBase<SomeNode> { }

This does however create a different inheritance structure than you have in your question. SomeNode no longer derives from Node so Node n = new SomeNode() is no longer value. They also no longer share a single interface. Node implements INode<Node> and SomeNode implements INode<SomeNode> which are different interfaces.

shf301
  • 31,086
  • 2
  • 52
  • 86