Унаследованный универсальный конструктор C # - PullRequest
5 голосов
/ 08 февраля 2012

Привет, я пытаюсь сделать общий триод.Вот абстрактный обобщенный класс

public abstract class TreeNode<T>
{
    protected List<TreeNode<T>> _childNodes = new List<TreeNode<T>>();
    protected TreeNode<T> ParentNode;

    public T ObjectData { get; set; }

    public TreeNode( TreeNode<T> parent, T data)
    {
        ParentNode = parent;
        ObjectData = data;
    }    
}

Он имеет сопутствующий интерфейс

interface TreeNodeOperations<T>
{
    //Adds child to tree node
    public abstract void AddChild<T>(T child);
    //Performs N-Tree search
    public abstract TreeNode<T> SeachChild<T>(T child);
}

Я пытаюсь унаследовать оба из них:

public class FHXTreeNode<T>: TreeNode<T>, TreeNodeOperations<T> where T : ParserObject
{
    public FHXTreeNode(FHXTreeNode<T> parent, T data) ---> # **ERROR** #
    {
        ParentNode = parent;
        ObjectData = data;
    }

    //Adds child to tree node
    public override FHXTreeNode<T> AddChild<ParserObject>(T childData)
    {
        FHXTreeNode<T> child = new FHXTreeNode<T>(this, childData);

        //_childNodes.Add(child);        

        return child;
    }

}

Ошибка: 'Parser.Objects.TreeNode' не содержит конструктор, который принимает 0 аргументов

Help Pls!

Ответы [ 4 ]

9 голосов
/ 08 февраля 2012

Вам необходимо добавить вызов в конструктор базового класса.

И, следовательно, вам не нужно устанавливать свойства внутри конструктора FHXTreeNode, поскольку он обрабатывается в конструкторе базового класса.Ваш новый конструктор должен выглядеть так:

public FHXTreeNode(FHXTreeNode<T> parent, T data) : base(parent, data)
{
}
5 голосов
/ 08 февраля 2012

Вам нужно вызвать конструктор базового класса.Если вы пропустите вызов :base(...), будет вызван конструктор без параметров базового класса.Поскольку ваш базовый класс не имеет такого конструктора, вы получаете ошибку.

public FHXTreeNode(FHXTreeNode<T> parent, T data)
   :base(parent, data)
{
}

Вызов параметризованного конструктора базового класса также делает инициализации поля устаревшими, поскольку они уже назначены в базовом классе.

В C # вы не можете наследовать конструкторы.Вы создаете новый конструктор в производном классе, который имеет ту же сигнатуру, что и конструктор базового класса.


Ваш интерфейс тоже поврежден: вы не можете объявить методы как public abstract в интерфейсе,Методы интерфейса всегда неявно общедоступны и никогда не имеют реализации.Таким образом, эти модификаторы будут избыточными и недопустимыми.


Далее вы не можете override методы интерфейса.Методы virtual / abstract можно переопределять только из базового класса .Если у вас есть метод, который соответствует методу в интерфейсе, он реализует этот метод интерфейса.


Еще одна ошибка заключается в том, что вы повторно используете параметр типа в методах интерфейса: void AddChild<T>(T child); неверно.Этот синтаксис предназначен для введения параметров типа в метод.Но вы хотите использовать параметр типа из содержащего типа.Поэтому вы должны написать AddChild(T child);.


Также есть несколько стилистических проблем: Имена интерфейсов должны начинаться с префикса I.И я бы по возможности избегал protected полей.

3 голосов
/ 08 февраля 2012

Прежде всего, public и abstract не являются допустимыми ключевыми словами в объявлениях интерфейса. Ваш интерфейс должен выглядеть так:

interface TreeNodeOperations<T>
{
    //Adds child to tree node
    void AddChild(T child);
    //Performs N-Tree search
    TreeNode<T> SeachChild(T child);
}

Чтобы ответить на ваш вопрос, поскольку TreeNode не определяет конструктор без параметров, например:

public TreeNode() { }

... тогда экземпляр FHXTreeNode не может быть создан без вызова его базового конструктора, например:

public FHXTreeNode(FHXTreeNode<T> parent, T data) : base(parent, data) { }
3 голосов
/ 08 февраля 2012

Вы должны вызывать конструктор базового класса из конструктора FHXTreeNode:

public FHXTreeNode(FHXTreeNode<T> parent, T data)
    : base(parent, data)
{
    ParentNode = parent;
    ObjectData = data;
}

Кроме того, по соглашению интерфейсы начинаются с заглавной буквы I в .NET, поэтому TreeNodeOperations должен быть ITreeNodeOperations

...