简体   繁体   中英

Is there any way to define a generic method in a super class to reference the inheriting class's type?

When defining something like this method:

class State {
   public void addOperator(Operator<? extends State> op) {
   }
}

Is there any way to define it in this way:

class State {
  public void addOperator(Operator<? extends this.getClass()> op) {
  }
}

So that any class inherting from forces all passed in value to conform to its class-type. 继承的任何阶级都会迫使所有传递的价值都符合其阶级类型。

I know that the above wont work, but is there anyway to force a generic wild-card to at least match the current classes type?

You already accepted an answer that claims your desired constraint can't be expressed in Java. If I understand the requirements correctly, the following solution comes close.

// You didn't flesh out what an operator does or provides,
// so I'll just make something up.
interface Operator<T> {
  void apply(T arg);
}

// Request that a derived type provide its own type as a type
// parameter, per the Curiously Recurring Template Pattern (CRTP).
abstract class State<T extends State> {
  public void addOperator(Operator<? extends T> op) {
    final PrintStream s = System.out;
    s.print("Received an operator of concrete type ");
    s.print(op.getClass().getName());
    s.println('.');
  }
}

final class DerivedState extends State<DerivedState> {
}

public class Driver {
  public static void main(String[] args) {
    DerivedState ds = new DerivedState();
    ds.addOperator(new Operator<DerivedState>() {
      // ...
    });

    // And the following will not compile:
    ds.addOperator(new Operator<Integer>() { /* ... */ });
  }
}

Note that DerivedType 's apply() method will only accept an Operator argument whose type parameter is DerivedType —or some type derived from DerivedType , but since DerivedType is final, no other such types exist.

What we can't do—which may be what Chris was alluding to—is mandate that the type parameter provided to State is in fact the derived type itself. We can't prevent the following definition, where one class supplies another as the type parameter for State :

final class AnotherDerivedState extends State<DerivedState> {
}

Here, one could call AnotherDerivedState#addOperator() with an Operator<DerivedState> , which is obviously not of type Operator<AnotherDerivedState> .

You can't prevent someone from deriving from State "incorrectly", but if you assume that people will follow the intended derivation pattern, you can help them use the rest of your library safely.

由于包含多态性,可以随时使用子类代替超类。

Try writing

State.class

to get the Class object of State.

class State {
  public void addOperator(Operator<? extends State.class> op) {
  }
}

Although I am not sure that Class object inherit among them, they use generics, Class<T> .

So let's say we have class Base , and class Derived extends Base . Class<Derived> probably does extends Class<Base> .

Instead, this scenario looks more promising

class State {
  public void addOperator(Operator<Class<? extends State>> op) {
  }
}

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