How to ensure this is the generic type specified in my class signature?

Suppose we have three classes - AbstractMessage, AbstractEngineand AbstractAction. These three classes all refer to each other in a general way, so each engine has a corresponding message and action, and you can refer to them directly in the code.

public class MyMessage<M extends AbstractMessage<M,E,A>, E extends AbstractEngine<M,E,A>, A extends AbstractAction<M,E,A>> {

This works fine, but when I try to enforce behavior at the highest level, I run into some problems. My AbstractAction class has a method applyTodefined this way:

protected abstract M applyTo(E engine, Object guarantee);

and my AbstractEngine class has this

private final M apply(A action) {
    return action.apply(this, this.guarantee);
}

And on this line he refuses - complains that:

The method applyTo(E, Object) in the type AbstractAction<M,E,A> is not
applicable for the arguments (AbstractEngine<M,E,A>, Object)

- E - , , , , E.

: , class MyEngine extends AbstractEngine<M...,E...,A...>, MyEngine E? AbstractEngine?

, .

class EngineExample {

    static abstract class AbEng<A extends AbAct<A,M,E>, M extends AbMes<A,M,E>, E extends AbEng<A,M,E>> {

        final M func(A act) {
            return act.apply(this); // compile error here
        }

    }

    static abstract class AbMes<A extends AbAct<A,M,E>, M extends AbMes<A,M,E>, E extends AbEng<A,M,E>> {

    }

    static abstract class AbAct<A extends AbAct<A,M,E>, M extends AbMes<A,M,E>, E extends AbEng<A,M,E>> {

        abstract void apply(E e);

    }

    static class RealEng extends AbEng<RealAct, RealMes, RealEng> {

    }

    static class RealMes extends AbMes<RealAct, RealMes, RealEng> {

    }

    static class RealAct extends AbAct<RealAct, RealMes, RealEng> {

        void apply(RealEng eng) {
            System.out.println("applied!");
        }
    }

}
+4
2

- this isInstanceOf E. , , , , .

abstract Action<E> {
  public void apply(Engine<?> e, Object o) {
    e.doSomething(o);
  }
}

abstract Action<E> {
  <T extends Engine<?>> public T apply(T e, Object o) {
    return e.doSomething(o);
  }
}

, 3 .

abstract System<A extends Action, M extends Message, E extends Engine> {
    abstract void apply(A action, E engine) {
        engine.render(action.apply())
    }
}

, - 3 . " - " , .

, , .

private final E dis = (E) this;

, , / .


( ). , , A B , A B .

,

MVCe, , . , Type , , . ( , .)

class test {

    public static void main(String[] rawrs) {
        RealEng re = new RealEng();
        RealAct ra = new RealAct();
        MockAct ma = new MockAct();
        ra.apply(re);
        // Remove all code related to Type interface if next line should compile
        ma.apply(re); // compile error here
    }

    static interface Type {
    }

    static interface Real extends Type {
    };

    static interface Mock extends Type {
    };

    static abstract class AbEng<T extends Type> {

        final void func(AbAct<T> act) {
            act.apply(this); // compile error here
        }

    }

    static abstract class AbMes<T extends Type> {

    }

    static abstract class AbAct<T extends Type> {

        abstract void apply(AbEng<T> e);

    }

    static class RealEng extends AbEng<Real> {

    }

    static class RealMes extends AbMes<Real> {

    }

    static class RealAct extends AbAct<Real> {
        @Override
        void apply(AbEng<Real> eng) {
            System.out.println("applied!");
        }
    }

    static class MockAct extends AbAct<Mock> {
        @Override
        void apply(AbEng<Mock> eng) {
            System.out.println("applied!");
        }
    }

}
+3

Java- .

, , , this E; , this, , Engine<M, A, E>, E.

, ((E)this), , ( javadoc ), Engine E ,

, E , Engine<M, A, E>.

protected abstract M applyTo(AbstractEngine<M, A, E> engine, Object guarantee);

. , ? - , , , /?

E applyTo, - E AbstractEngine, apply. this, , .:

public class AbstractEngine<M extends ..., A extends ..., E extends ...> {
    private final E engine;

    protected AbstractEngine(final E engine) {
       this.engine = Objects.requiresNonNull(engine);
    }
}

public class MyEngine extends AbstractEngine<MyMessage, MyAction, MyEngine> {
    public MyEngine() {
       super(this);
    }
}

, MyEngine, , MyEngine E, "cast" . AbstractEngine .

, this, , , , .

, , apply. , ... , AbstractEngine, this , .

protected AbstractEngine(final E engine) {
   if (engine != this) {
      throw new IllegalArgumentException();
   }
   this.engine = engine;
}

, ... , , , , AbstractEngine , .

+2
source

Source: https://habr.com/ru/post/1682788/


All Articles