简体   繁体   中英

Java: How to reference the implementing type of an interface with generics on the interface?

Given:

interface Data<M extends Data<?, ?>, T extends Data<?, ?>> {
  M modify(Modifier<M>);
  T transform(Transformer<T>);
}

interface Modifier<M extends Data<?, ?>> {
  M modify(InteralValue a, InternalValue b);
}

interface Transformer<T extends Data<?, ?>> {
  T transform(InteralValue a, InternalValue b);
}

Which makes implementors look like this:

class A implements Data<A, B> {
  A modify(Modifier<A> modifier) {
     return modifier.modify(this.a, this.b);
  }
  B transform(Transformer<B> transformer) {
     return transformer.transform(this.a, this.b);
  }
}

class B implements Data<B, C> {
  B modify(Modifier<B> modifier) {
     return modifier.modify(this.a, this.b);
  }
  C transform(Transformer<C> transformer) {
     return transformer.transform(this.a, this.b);
  }
}
... and so for C, D, etc...

Is it possible to either limit M to be only the current implementor of Data (in this case A), or remove M altogether (reference M in such a way the current interface implementor is the limiter of M)?

To clarify, the transform function is intended to change from one type to the next (B b = A.transform(Z) where Z is a Transformer), while the modify function is intended to return the same type, but with different internals.

If you want to limit M to be only A,remove M altogether and keep only T

interface Data<T extends Data<?, ?>> {
  A modify(Modifier);
  T transform(Transformer<T>);
}

interface Modifier {
  A modify(InteralValue a, InternalValue b);
}

interface Transformer<T extends Data<?, ?>> {
  T transform(InteralValue a, InternalValue b);
}
Which makes implementors look like this:

class A implements Data<B> {
  A modify(Modifier modifier) {
     return modifier.modify(this.a, this.b);
  }
  B transform(Transformer<B> transformer) {
     return transformer.transform(this.a, this.b);
  }
}

No, there is no way to refer to the type of the implementing class in Java. If it were possible to do this, it would cause problems with inheritance that cannot be handled by the current type system in Java:

interface Foo {
    Self foo();
}
class Bar implements Foo {
    Bar foo() { return new Bar(); }
}
class Baz extends Bar { }

Interface implementation is inherited in Java, so Baz should implement the interface Foo ; however, Baz does not implement a foo() method that returns Baz , as required by interface Foo .


By the way, the bounds don't serve much purpose; if you remove them your code will work just as well:

interface Data<M, T> {
  M modify(Modifier<M>);
  T transform(Transformer<T>);
}

interface Modifier<M> {
  M modify(InteralValue a, InternalValue b);
}

interface Transformer<T> {
  T transform(InteralValue a, InternalValue b);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM