Zachary Sweigart
Zachary Sweigart

Reputation: 1111

Java Cyclic Generics

How can I get type safety for a set of classes when there are cyclic relationships. I have 3 classes, Router, Interactor and Component such that

abstract class Router<C extends Component, I extends Interactor>
abstract class Interactor<R extends Router>
abstract class Component<I extends Interactor>

I want to ensure that a specific router is tied to a specific component and specific interactor.

Edit The architecture of the app ensures that we have exactly 1 router for 1 interactor for 1 component. Some reuse is possible but if router A is with interactor A and component A it will always be that way, otherwise we would define router B with interactor A and component B for example.

Edit 2 A more concrete example: We can have the login screen which has loginscreenrouter, loginscreeninteractor and loginscreencomponent and then the loading screen which has 3 more classes in the same structure. But what we don't want is for developers to accidentally pass the loadingscreeninteractor to the loginscreenrouter

Upvotes: 8

Views: 209

Answers (1)

Tom Hawtin - tackline
Tom Hawtin - tackline

Reputation: 147164

Each type will need a parameter for each of the types including itself.

abstract class Router<
    R extends Router<R,C,I>, C extends Component<R,C,I>, I extends Interactor<R,C,I>
> { }

abstract class Interactor<
    R extends Router<R,C,I>, C extends Component<R,C,I>, I extends Interactor<R,C,I>
> { }

abstract class Component<
    R extends Router<R,C,I>, C extends Component<R,C,I>, I extends Interactor<R,C,I>
>  { }

I guess another way around, that I haven't seen before, is to push all the interactions into one type. Less angles, but doesn't feel very OO and perhaps causes more work.

import java.util.Set;

interface System<R extends Router, C extends Component, I extends Interactor> {
    Set<R> routers(I interactor);
    Set<R> routers(C component);
    Set<I> interactors(R router);
    Set<I> interactors(C component);
    Set<C> components(R router);
    Set<C> components(I interactor);
}

abstract class Router {}

abstract class Interactor {}

abstract class Component { }

Upvotes: 8

Related Questions