2016-08-02 10 views
2

Ich habe eine Frage here gefunden, dass fast meine Frage beantwortet, aber ich verstehe immer noch nicht vollständig.Inner Klasse generische Art gleiche wie äußere Art

einen Baum Datenstruktur schreiben Der Versuch, ich habe dies:

public class Tree<T> 
{ 
    public TreeNode<T> root; 
    ... 

    public class TreeNode<T> 
    { 
     List<TreeNode<T>> children; 
     T data; 
     public T Data { get { return data; } } 

     public TreeNode<T>(T data) 
     { 
      this.data = data; 
      children = new List<TreeNode<T>>(); 
     } 
     ... 
    } 
} 

Und jeder, der anscheinend mit C# Generika gearbeitet hat, weiß, dass ich diese Compiler-Warnung bekam: Type parameter 'T' has the same name as the type parameter from outer type 'Tree<T>'

Meine Absicht war, zu schaffen eine innere Klasse, die gezwungen wäre, den gleichen Typ wie die äußere Klasse zu verwenden, aber ich verstehe jetzt, dass das Hinzufügen eines Typparameters der inneren Klasse erlaubt, flexibler zu sein. Aber in meinem Fall möchte ich Subklassen von Tree<T> der Lage sein, TreeNode zu verwenden, zum Beispiel wie folgt aus:

public class IntTree : Tree<int> 
{ 
    ... 
    private static IntTree fromNode(TreeNode<int> node) 
    { 
     IntTree t = new IntTree(); 
     t.root = node; 
     return t; 
    } 
} 

(Diese Methode der Unterklasse ToString() rekursiv zu implementieren erlaubt)

Also meine Frage ist wenn ich die Parametrierung nehmen, wie folgt aus:

public class Tree<T> 
{ 
    public TreeNode root; 
    ... 

    public class TreeNode 
    { 
     List<TreeNode> children; 
     T data; 
     public T Data { get { return data; } } 

     public TreeNode(T data) 
     { 
      this.data = data; 
      children = new List<TreeNode>(); 
     } 
     ... 
    } 
} 

wird die resultierende Unterklasse gezwungen werden, ganze Zahlen zu verwenden, wenn TreeNode s zu schaffen, und deshalb nie die Absicht brechen können, ich ha d?

Haftungsausschluss: Ja, ich weiß, dass ich hier wahrscheinlich viel falsch mache. Ich lerne immer noch C#, hauptsächlich aus Java und Lisp, mit ein wenig schlichter C, also sind Anregungen und Erklärungen willkommen.

Antwort

2

Ja, es wird gezwungen werden, zu verwenden der gleiche Typ. Schauen Sie sich die Erklärung wieder:

public class Tree<T> 
{ 
    public class TreeNode 
    { 
     private T Data; 
    } 
} 

So ist die Art von Data bestimmt, wenn Sie eine bestimmte Tree instanziiert:

var tree = new Tree<int>(); 

diese Weise die Art der Data als int deklariert und kann nicht anders sein.

Beachten Sie, dass es keine nicht-generische TreeNode Klasse gibt. Es gibt nur ein Tree<int>.TreeNode Typ:

Tree<int> intTree = new Tree<int>(); // add some nodes 
Tree<int>.TreeNode intNode = intTree.Nodes[0]; // for example 

Tree<string> stringTree = new Tree<int>(); // add some nodes 
Tree<string>.TreeNode stringNode = stringTree.Nodes[0]; // for example 

// ERROR: this won't compile as the types are incompatible 
Tree<string>.TreeNode stringNode2 = intTree.Nodes[0]; 

A Tree<string>.TreeNode ist ein verschiedene Typ als Tree<int>.TreeNode.

+0

Ok, das macht viel mehr Sinn. Da 'TreeNode' eine innere Klasse ist, kann' TreeNode' nicht ohne _typed_ 'Tree ' erstellt werden. Obwohl die Unterklasse es wie 'TreeNode' verwenden kann, ist es implizit 'Tree .TreeNode'. –

+1

@ KristenHammack Genau. Innerhalb der 'Baum ' Klasse können Sie es als' TreeNode' bezeichnen, da der Compiler weiß, was Sie meinen.Außerhalb dieses Bereichs müssten Sie explizit angeben, auf was sich _kind of_ 'TreeNode' bezieht (z. B." Tree .TreeNode "). –

0

Der Typ T in der äußeren Klasse bereits erklärt, in allen seinen inneren Erklärungen verwendet werden kann, so dass Sie einfach die <T> von der inneren Klasse entfernen:

public class Tree<T> 
{ 
    public TreeNode root; 
    //... 

    public class TreeNode 
    { 
     List<TreeNode> children; 
     T data; 
     public T Data { get { return data; } } 

     public TreeNode(T data) 
     { 
      this.data = data; 
      children = new List<TreeNode>(); 
     } 
     //... 
    } 
}