在抽象方法中声明的动态 return 类型的实现

Dynamic return type of implementation declared in abstract method

我正在寻找一种方法,在抽象方法中使 return 类型成为调用该方法的实现之一。

换句话说,我想写这样的东西:

public class GenericClass {

  public <T extends GenericClass> T returnMyself() {
    return (T)this; // Compiler warning, unsafe cast
  }
}

public class Implem1 extends GenericClass {}

public class Implem2 extends GenericClass {}

public class Main {

  public static void main(String[] args) {
    Implem1 implem1 = new Implem1();
    Implem1 again1 = implem1.returnMyself(); // Works fine, the type is inferred by the type of again1, I think
    Implem1 again2 = implem1.<Implem1>returnMyself(); // Works fine, the type is explicitly asked by <Implem1>
    Implem2 again3 = implem1.returnMyself(); // Works fine while it shouldn't. 
  }

}

我正在寻找的是一种声明方法的方法,以便在编译时,returnMyself() 只能 return 调用它的实现类型(在我的示例中, implem1 是 Implem1 类型),并确保调用的代码不能 mistake/mix 类型。

我搜索了很多但找不到我的答案(有些主题看起来相似但想要更一般的情况,而不是明确调用该方法的实现类型)。

一些答案是正确的,但总是暗示要覆盖每个实现中的方法 class,这对我来说可能很麻烦且容易出错。理想情况下,我正在寻找一种只需要在摘要 class.

中编写一次的方法

任何 help/answer 赞赏 :D

既然您想在子类中编写这些方法,这似乎是可行的。您可以覆盖方法并使用不同的 return 类型,只要新的 return 类型是旧类型的扩展:

Can overridden methods differ in return type?

你可以这样做:

public class Parent {
    public Parent returnMyself() {
        return this;
    }
}

public class Child extends Parent {
    public Child returnMyself() {
        return this;
    }
}

这没问题,因为如果您将 Child 实例存储在 Parent 变量中,那么您期望 Parent return 类型的 returnMyself()。即使它实际上是一个 Child 对象,由 returnMyself() 编辑的 Child return 扩展了 Parent 所以你去吧。

既然你在问题描述中提到了抽象,那么遵循类似于 Java 的 Enum class 的模型如何,其中通用类型在 class 定义?

public abstract class GenericClass<T extends GenericClass> {

    public abstract T returnMyself();
}

public class Implem1 extends GenericClass<Implem1> {

    @Override
    public Implem1 returnMyself() {
        return this;
    }
}

public class Implem2 extends GenericClass<Implem2> {

    @Override
    public Implem2 returnMyself() {
        return this;
    }
}

public class Main {

    public static void main(String[] args) {
        Implem1 implem1 = new Implem1();
        Implem1 again1 = implem1.returnMyself(); // Works fine
        Implem1 again2 = implem1.returnMyself(); // Works fine
        Implem2 again3 = implem1.returnMyself(); // Does not compile 
    }

}