简体   繁体   English

有什么方法可以在超类中定义泛型方法以引用继承类的类型?

[英]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 State 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. 您已经接受了一个声称无法用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. 注意, DerivedTypeapply()方法将只接受类型参数为DerivedType或从DerivedType派生的某种类型的Operator参数,但由于DerivedType是最终类型,因此不存在其他此类类型。

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. 我们无法做的(可能是Chris所暗示的)是强制提供给State的类型参数实际上是派生类型本身。 We can't prevent the following definition, where one class supplies another as the type parameter for State : 我们不能阻止以下定义,其中一个类提供另一个作为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> . 在这里,可以使用Operator<DerivedState>调用AnotherDerivedState#addOperator() ,该Operator<DerivedState>显然不是 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. 您不能阻止某人“不正确地”导出State ,但是如果您假设人们会遵循预期的派生模式,则可以帮助他们安全地使用图书馆的其余部分。

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

Try writing 尝试写作

State.class

to get the Class object of State. 获取状态的Class对象。

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> . 尽管我不确定Class对象是否在它们之间继承,但是它们使用泛型Class<T>

So let's say we have class Base , and class Derived extends Base . 假设我们有class Base class Derived extends Base Class<Derived> probably does extends Class<Base> . Class<Derived>可能会扩展Class<Base>

Instead, this scenario looks more promising 相反,这种情况看起来更有希望

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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