2015-09-04 1 views
0

J'ai un problème avec Classes and Interfaces. Je veux réaliser qu'une interface déclare une méthode qui prend le type de la classe implémentée. Lorsque j'hérite de cette classe, la méthode ne doit prendre que le type de la classe héritée.Vérification des types de paramètres lors de l'implémentation de l'interface et de l'héritage

Est-ce possible?

Un code court 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! 
} 
+0

Si c'est possible, c'est probablement moche. Par exemple, vous pouvez lancer une exception si le noeud n'est pas un noeud. Mais cela donne l'exécution et ne compile pas la vérification du temps. –

Répondre

0

Vous pouvez obtenir essentiellement ce que vous décrivez en faisant INode générique sur le type de nœud et en utilisant une classe de base générique pour votre noeud de. Le type de noeud générique sera utilisé pour permettre à une seule mise en œuvre d'utiliser différents 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> { } 

Cela ne crée cependant une structure d'héritage différent de celui que vous avez dans votre question. SomeNode ne dérive plus de Node donc Node n = new SomeNode() n'a plus de valeur. Ils ne partagent plus une seule interface. Node implémente INode<Node> et SomeNode implémente INode<SomeNode> qui sont des interfaces différentes.