Creating circular generic references

I am writing an application to do some distributed calculations in a peer to peer network. In defining the network I have two class the P2PNetwork and P2PClient. I want these to be generic and so have the definitions of:

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

P2PClient<T extends P2PNetwork<? extends T>>

with P2PClient defining a method of setNetwork(T network). What I am hoping to describe with this code is:

  1. A P2PNetwork is constituted of clients of a certain type
  2. A P2PClient may only belong to a network whose clients consist of the same type as this client (the circular-reference)

This seems correct to me but if I try to create a non-generic version such as

MyP2PClient<MyP2PNetwork<? extends MyP2PClient>> myClient;

and other variants I receive numerous errors from the compiler. So my questions are as follows:

  1. Is a generic circular reference even possible (I have never seen anything explicitly forbidding it)?
  2. Is the above generic definition a correct definition of such a circular relationship?
  3. If it is valid, is it the "correct" way to describe such a relationship (i.e. is there another valid definition, which is stylistically preferred)?
  4. How would I properly define a non-generic instance of a Client and Server given the proper generic definition?

Answers


Circular generic references are indeed possible. Java Generics and Collections includes several examples. For your case, such a specimen would look like this:

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);

It might help us to answer you if you further defined what "a certain type" means, i.e. what the differences are between various "types" of P2PNetworks.

But instead of expressing the dependency / circular relationship in terms of each other, it might be easier to express by introducing a third class, the P2PType:

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

I might be overlooking something but I think this would allow the compiler to enforce that P2PClients are a part of P2PNetworks of the same generic type.

This approach might fall apart however if the "type" isn't something that is suitable to express as a object-oriented itself, i.e. if the P2PType isn't something that would have methods, polymorphic behavior, etc.


Need Your Help

VBA on arrays runs too slow

excel vba

The file I work on contains about 80,000 rows

httpwebrequest sending a file

c# upload httpwebrequest

I need to upload a file in C# using an httpwebrequest. I don't need to post any form data. It's a scheduled task that will run once a night and upload a file to a server. It will need to set the