21

我正在编写一个应用程序来在对等网络中进行一些分布式计算。在定义网络时,我有两类 P2PNetwork 和 P2PClient。我希望这些是通用的,因此具有以下定义:

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

P2PClient<T extends P2PNetwork<? extends T>>

使用 P2PClient 定义 setNetwork(T network) 的方法。我希望用这段代码描述的是:

  1. P2PNetwork 由某种类型的客户端组成
  2. P2PClient 只能属于其客户端与该客户端(循环引用)相同类型的网络

这对我来说似乎是正确的,但如果我尝试创建一个非通用版本,例如

MyP2PClient<MyP2PNetwork<? extends MyP2PClient>> myClient;

和其他变体我从编译器收到许多错误。所以我的问题如下:

  1. 通用循环引用是否可能(我从未见过任何明确禁止它的东西)?
  2. 上述通用定义是对这种循环关系的正确定义吗?
  3. 如果它是有效的,它是否是描述这种关系的“正确”方式(即是否有另一个有效的定义,在风格上是首选的)?
  4. 给定正确的通用定义,我将如何正确定义客户端和服务器的非通用实例?
4

2 回答 2

29

循环通用引用确实是可能的。Java 泛型和集合包括几个示例。对于您的情况,这样的样本将如下所示:

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);
于 2010-04-16T20:48:12.900 回答
3

如果您进一步定义“某种类型”的含义,即 P2PNetworks 的各种“类型”之间的区别,它可能会帮助我们回答您。

但是,与其用彼此来表达依赖/循环关系,不如通过引入第三个类来更容易地表达P2PType

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

我可能忽略了一些东西,但我认为这将允许编译器强制 P2PClients 是相同泛型类型的 P2PNetworks 的一部分。

但是,如果“类型”不适合表达为面向对象本身,即如果P2PType不是具有方法、多态行为等的东西,这种方法可能会失败。

于 2010-04-02T16:00:03.297 回答