Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Cyclic Generics

Tags:

java

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

like image 213
Zachary Sweigart Avatar asked Jan 04 '19 22:01

Zachary Sweigart


1 Answers

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 { }
like image 73
Tom Hawtin - tackline Avatar answered Oct 24 '22 04:10

Tom Hawtin - tackline