2010-04-02 2 views
17

Я пишу приложение для выполнения некоторых распределенных вычислений в одноранговой сети. При определении сети у меня есть два класса P2PNetwork и P2PClient. Я хочу, чтобы они были универсальными и поэтому имеют определения:Создание круговых общих ссылок

P2PNetwork<T extends P2PClient<? extends P2PNetwork<T>>> 

P2PClient<T extends P2PNetwork<? extends T>> 

с P2PClient определения метода setNetwork (T сети). То, что я надеюсь, чтобы описать этот код:

  1. P2PNetwork состоит из клиентов определенного типа
  2. P2PClient может принадлежать только к сети, чьи клиенты состоят из же типа, как это клиент ( круговая ссылка)

Это кажется правильным для меня, но если я пытаюсь создать не-дженерик, такой как

MyP2PClient<MyP2PNetwork<? extends MyP2PClient>> myClient; 

и другие варианты Я получаю многочисленные ошибки от компилятора. Так что мои вопросы заключаются в следующем:

  1. Является ли общий циклическая даже возможно (я никогда не видел ничего явно запрещающую его)?
  2. Является ли приведенное выше общее определение правильным определением такого кругового отношения ?
  3. Если это действительно, это «правильный» способ описать такие отношения (т.е. есть другое действительный определение, которое стилистический предпочтительные)?
  4. Как правильно определить необязательный экземпляр клиента и сервер с учетом правильного общего определения ?
+0

я до сих пор не удалось найти однозначный ответ на «возможно», однако от дальнейшего чтения и попытки я считаю, что можно создать но не для создания объектов, использующих его. –

ответ

24

Циркулярные общие ссылки действительно возможны. Java Generics and Collections содержит несколько примеров.В вашем случае, такой образец будет выглядеть следующим образом:

public interface P2PNetwork<N extends P2PNetwork<N, C>, 
          C extends P2PClient<N, C>> { 
    void addClient(C client); 
} 

public interface P2PClient<N extends P2PNetwork<N, C>, 
          C extends P2PClient<N, C>> { 
    void setNetwork(N network); 
} 

class TorrentNetwork implements P2PNetwork<TorrentNetwork, TorrentClient> { 
    @Override 
    public void addClient(TorrentClient client) { 
    ... 
    } 
} 

class TorrentClient implements P2PClient<TorrentNetwork, TorrentClient> { 
    @Override 
    public void setNetwork(TorrentNetwork network) { 
    ... 
    } 
} 

... 

TorrentNetwork network = new TorrentNetwork(); 
TorrentClient client = new TorrentClient(); 

network.addClient(client); 
+2

Хорошо, так что ваш ответ был 6 лет назад, но он все еще помог мне решить массивную головную боль, которую я пытался получить Game <...> и GamePlayer <...>, чтобы работать правильно! Определенно, моя любимая вещь в Stack Exchange. – corsiKa

3

Это может помочь нам ответить вам, если вы определили, что означает «определенный тип», то есть различия между различными «типами» P2PNetworks.

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

public class P2PNetwork<T extends P2PType> { 
    ... 
} 
public class P2PClient<T extends P2PType> { 
    ... 
    public void setNetwork(P2PNetwork<T> network) { ... } 
} 

я мог бы быть видом что-то, но я думаю, что это позволит компилятору обеспечить, чтобы P2PClients были частью P2PNetworks того же родового типа.

Этот подход может развалиться, однако, если «тип» не является чем-то подходящим для выражения как объектно-ориентированного, то есть, если P2PType не является тем, что имеет методы, полиморфное поведение и т. Д.

+0

Эта мысль является целью сети. Надуманный пример: сеть для вычисления чисел Фибонначчи против простых чисел и определение смысла жизни. Предпосылка - базовый класс сети отвечает за поддержание состояния и связности сети, базового клиента для распространения информации о сети и обработки фактической задачи сети. Тем не менее, это также стало академическим интересом к тому, насколько возможны круговые общие определения, и если да, то как они будут достигнуты. –