2015-04-19 3 views
0

Я пытаюсь представить график с узлами и краями.«Импортировать» общий тип из другого класса в Java

У меня есть класс Node, который должен быть:

public class Node<NodeType> 

и другой класс Edge, который я позволил спараметрировать каким-либо образом. Сначала я думал, что Edge<EdgeType>, но так как они имеют Узлы как atribute, я в конечном итоге делаю следующее (в основном потому, что Eclipse, рассказал мне о Узле быть сырым типом, если я не параметрирования)

public class Edge<EdgeType, NodeType> { 
    private Node<NodeType> start; 
    private Node<NodeType> end; 
    private EdgeType value; 
    ... 
} 

Это дает мне способность работать без проблем в классе Эджа, но есть некоторые методы в классе Node, которые требуют работу с кромками, такие как

public List<EdgeType> edgesValues(Node<NodeType> node) { 
    /*Returns a list of values of the edges between the node it is called on and the node given by argument*/ 
} 

, которые я не могу использовать, потому что EdgeType не определена. Поскольку я не могу добавить еще один параметр в класс Node, я не знаю, как «импортировать» EdgeType в него.

+0

Не могли бы вы объяснить более подробно, что это означает, что «есть некоторые методы в классе Node, которые требуют работы с Edges»? Вам даны строгие интерфейсы (возможно, даже модульные тесты)? Или это просто ваше * желание * иметь метод, подобный 'edgeValues'? Постарайтесь отделить жесткие требования (предписанные интерфейсы) от функций, которые вы сейчас считаете хорошими. Возможно, вы просто пытаетесь реализовать то, чего не должны, потому что ваше понимание интерфейсов является ошибочным. –

ответ

0

Ваше решение довольно простое, использовать общие методы:

public <EdgeType> List<EdgeType> edgesValues(Node<NodeType> node) { 

} 

но пропускание Node<NodeType> в качестве параметра в экземпляре Node<NodeType> не делает много смысла - Methinks вы получили себе недостаток дизайна прямо там, может быть, вы должны использовать другой шаблон проектирования

+0

Какова должна быть реализация? Что делать, если пользователь вызывает 'edgeValues ​​' на узле, который внутренне 'edgeValues ​​'? –

+0

Реализация может выглядеть точно так же, как и в моем примере кода. Если он вызван как в вашем вопросе, возвращается список '', но параметр должен иметь тип '', который может быть или не быть совместимым с '', конечно. В противном случае он не будет компилироваться. Thats красота genrics, я рекомендую прочитать учебное пособие по этому вопросу. – specializt

+0

Я думаю, мой вопрос недостаточно ясен. Предположим, что у вас есть два узла 'a',' b' типа 'Node ', которые связаны ребрами типа 'Edge '. Затем вы просто берете 'a' и вызываете' a.edgesValues ​​ (b) ', где' Bar' не имеет ничего общего с 'Foo'. Как компилятор должен понять, что что-то не так, если нет упоминания о 'Foo' в типах' a' и 'b'? –

0

Если «есть класс Node, который должен быть» нечто застывшее, то вы должны удалить EdgeType из Edge, вы не используете его в любом случае:

public class Edge<N> { 
    private Node<N> start; 
    private Node<N> end; 
    private int value; 
} 

В вашем Node классе, вы не нужны никакие дополнительные параметры типа в настоящее время:

public List<Edge<N>> edges(...) { ... } 

Вы, вероятно, не будет ничего более сложного, чем int-х в любом случае нужно.

+0

График должен быть выполнен таким образом, что и кромки, и узлы могут быть объектом любого типа, и я плохо говорю об этом. Изменить: на самом деле я написал NodeType вместо EdgeType для атрибута values. – Jurcan

+0

Сокращение сложности не всегда является решением. На самом деле, это может очень сильно УВЕЛИЧИТЬ сложность, если ваш шаблон дизайна больше не соответствует исходной задаче; возможно, потому, что вы уменьшили его до абсурда. Опытный инженер-программист знает, как найти золотой разрез между сложностью и простотой. – specializt

+0

@specializt Если квалифицированный инженер-программист не имеет права изменять интерфейсы в своей задаче о выполнении домашней работы, то писать самый примитивный код выброса * является хорошим решение. –

2

Я бы поставил edgesValues метод в отдельный класс, который параметризованных как NodeType и EdgeType:

class Node<N> { 
    N value; 
} 

class Edge<E, N> { 
    Node<N> from; 
    Node<N> to; 
    E value; 
} 

class Graph<E, N> {  
    Node<N> newNode(N nodeVal) { 
     ... 
    } 

    Edge<E, N> newEdge(E edgeVal, Node<N> from, Node<N> to) { 
     ... 
    } 

    List<E> edgesValues(Node<N> node) { 
     ... 
    } 
} 
+0

edgeValues ​​возвращает список значений ребер между вызываемым им узлом и узлом, заданным аргументом (отредактированным в сообщении), поэтому я не могу этого сделать. Я также не могу сделать это с двумя аргументами узла, поскольку задача заставляет меня вызывать метод из узла. – Jurcan

+0

Я чувствую, что есть некоторые вещи об этой задаче, которые отсутствуют в вашем описании. Единственный способ удовлетворить все эти ограничения - либо отказаться от безопасности типа компиляции, либо присвоить «Node» внутренний класс классу, параметризованному «EdgeType». – Misha

+0

Прочтите мой комментарий к ответу, который я принял. Я прошу прощения за то, что не объяснил ситуацию лучше. Тем не менее, я хотел бы поблагодарить вас за более прямой ответ «Единственный способ удовлетворить все эти ограничения - либо отказаться от безопасности типа компиляции, либо присвоить Node внутренний класс классу, параметризованному EdgeType», который действительно помог проблема. – Jurcan