Подтвердить что ты не робот

Создание круговых общих ссылок

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

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

P2PClient<T extends P2PNetwork<? extends T>>

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

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

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

MyP2PClient<MyP2PNetwork<? extends MyP2PClient>> myClient;

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

  • Является ли общая круговая ссылка ровной возможно (я никогда не видел ничего явно запрещающего его)?
  • Является ли приведенное выше общее определение a правильное определение такого кругового отношения?
  • Если это действительно так, то это "правильный" способ описания таких отношений (т.е. существует еще один действительный определение, которое является стилистическим предпочтительным)?
  • Как правильно определить не общий экземпляр Клиента и Сервер, получивший правильный общий определение?
4b9b3361

Ответ 1

Циркулярные общие ссылки действительно возможны. 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

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

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

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

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

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