2010-01-31 2 views
3

У меня есть родовое дерево, общий параметр тип данных хранятся в узлах:Реализации универсального интерфейса с сырым типом

class TreeNode<D>{ 
    public D data; 
    ..... 
} 

Затем интерфейс посетителя использовать вместе с деревом трансверсальным:

interface Visitor<D> { 
    void visit(TreeNode<D> node); 
} 

Некоторые посетители могут воспользоваться дженериков:

class DataListCreator<D> implements Visitor<D> { 
    List<D> dataList = new ArrayList<D>(); 
    public void visit(TreeNode<D> node) { 
     dataList.add(node.data); 
    } 
    public List<D> getDataList() { 
     return dataList; 
    } 

Но другие не делают, они будут соответствовать лучше в сыром классе

class NodeCounter implements Visitor { 
    private int nodeCount = 0; 
    public void visit(TreeNode node) { 
     nodeCount++; 
    } 
    public int count() { 
     return nodeCount; 
    } 

Но я не знаю, как реализовать этот последний случай, приведенный выше код не компилировать как я должен реализовать общий интерфейс не сырой один. Я пробовал внедрить

Visitor<?> 

с таким же результатом. Поэтому мой вопрос заключается в том, что я вынужден использовать общий тип

NodeCounter<D> 

для реализации интерфейса посетителя ?.

Спасибо.

ответ

1

Вкратце - да, вам нужно предоставить общий интерфейс аргументу типа.

Что вы, вероятно, должны сделать, является нереализованным (и, возможно, пустым) интерфейсом ITreeNode, который наследует ITreeNode<D>. Любые методы, которые не являются , нуждаются в, чтобы быть универсальными, вместо этого объявляются в этом межстрочном промежутке. Затем сделайте то же самое для IVisitor, а NodeCounter может наследовать не общий интерфейс Visitor.

Краткое схематичное:

ITreeNode 
ITreeNode<D> implements TreeNode 

IVisitor 
IVisitor<D> implements IVisitor 

NodeCounter implements IVisitor 

(Примечание: Я использовал C# соглашение с приставкой интерфейсов с I. NodeCounter предназначается, чтобы быть классом, в то время как другие интерфейсы ...)

+1

Что C# Конвенция должна умереть в огне. –

3

код выше не компилировать

я пытался компилировать ваш пример, и его работа в порядке. Я использую Java 6. Какова была ошибка компиляции?

Это то, что я успешно скомпилирован:

class TreeNode<D>{ 
    public D data; 
} 

interface Visitor<D> { 
    void visit(TreeNode<D> node); 
} 

class NodeCounter implements Visitor { 
    private int nodeCount = 0; 
    public void visit(TreeNode node) { 
     nodeCount++; 
    } 
    public int count() { 
     return nodeCount; 
    } 
} 
+0

О, да, указывая на то, что я использую устаревшую версию InelliJ от rahter, которая дала мне эту ошибку. Я буду обновлять все, так как я не очень доволен удвоением своих классов. – 2010-01-31 10:50:00

+0

Я тоже не буду этому рад :-) –

3

Java дженериков являются очень мощными, и сырые типы почти никогда не требуется. .

Вы, вероятно, хотите поставить некоторые символы в Например, посетитель может понадобиться не знать точный общий аргумент TreeNode ы его посещения:

interface TreeNodeVisitor<D> { 
    void visit(TreeNode<? extends D> node); 
} 

Возможно, лучше, TreeNode может (?) не нужно знать точный тип посетителя.

interface TreeNode<D> { 
    void accept(TreeNodeVisitor<? super D> visitor); 
} 
+0

В чем разница между: void visit (TreeNode node); и просто: пустое посещение (TreeNode узел); Я имею в виду, что в обоих случаях метод посещения будет иметь те же типы, что и аргумент. Или я ошибаюсь? Есть ли практическое преимущество в использовании этого более синтаксиса? – 2010-01-31 12:12:22

+0

@Tom, можете ли вы дать рабочий пример (например, компиляционный) классов в этом примере, который генерируется, как вы предлагаете? – Avi

+0

@Pepin, Если у вас был 'D' был' Object', то с помощью '? extends D' разрешает, скажем, 'TreeNode ' в качестве аргумента. –

1

Java Дженерики явно способны взаимодействовать с сырыми типов с использованием метода, известного как Erasure.

Так что ситуация вы описываете напрямую поддерживается и должен компилироваться:

class TreeNode<D>{ 
    public D data; 
} 

interface Visitor<D> { 
    void visit(TreeNode<D> node); 
} 

class NodeCounter implements Visitor { 
    private int nodeCount = 0; 
    public void visit(TreeNode node) { 
     nodeCount++; 
    } 
    public int count() { 
     return nodeCount; 
    } 
} 
+0

Спасибо, что посмотрели на это. Я обновляю свою реализацию Java, чтобы увидеть, что я могу избавиться от сообщенной ошибки, возможно, вызванной и старой версией IDE. – 2010-01-31 12:17:21

Смежные вопросы