【问题标题】:How to make a reference to a concrete subtype in an abstract method definition如何在抽象方法定义中引用具体子类型
【发布时间】:2022-01-15 22:33:40
【问题描述】:

假设我有以下定义:

public abstract class SomeAbstractClass {
    
    public abstract List<SomeAbstractClass> getNextElements() ;
}

如果我构建一个扩展 SomeAbstractClass 的具体类,例如命名为 SomeConcreteClass,我希望 getNextElements 具有以下签名:

public List<SomeConcreteClass> getNextElements()

代替:

public List<SomeAbstractClass> getNextElements()

换句话说,我希望我的抽象定义具有取决于当前具体类型的类型。可以做到吗?如果有,怎么做?

【问题讨论】:

  • 您可以将泛型类型添加到抽象基类并将其用于getNextElements() 方法。但是,getNextElements() 方法将如何使用?该方法的调用者可以看到/知道哪些类型?
  • @Progman 是的,我有点希望我不必那样做。我不愿意定义像MyConcreteClass&lt;MyConcreteClass&gt; 这样的类,尤其是因为它比我希望的更通用。关于您评论的第二部分,这有什么关系?为简单起见,我想我们可以假设调用者可以看到所有内容。
  • @MrO 问题可能是您无论如何都不能这样做,因为该方法的使用者可能无论如何都看不到具有调整后返回类型的方法。但这取决于您拥有的系统。

标签: java generics


【解决方案1】:

只使用 Java 泛型:

public abstract class SomeAbstractClass<T extends SomeAbstractClass> {
    public abstract List<T> getNextElements() ;
}
public class SomeConcreteClass extends SomeAbstractClass<SomeConcreteClass> {
    @Override
    public List<SomeConcreteClass> getNextElements() {
        return new ArrayList<>();
    }
}

另一种可能性是只使用如下泛型方法:

public abstract class SomeAbstractClass {
    public abstract <T extends SomeAbstractClass> List<T> getNextElements();
}
public class SomeConcreteClass extends SomeAbstractClass {
    @Override
    public List<SomeConcreteClass> getNextElements() {
        return new ArrayList<>();
    }
}

这样做的缺点是您现在在 List&lt;SomeConcreteClass&gt; getNextElements() 处有未经检查的转换,这可能会在运行时触发 ClassCastException

【讨论】:

  • 我想我可以使用这样的技巧,但这似乎有点多余,我希望有另一种解决方案。我想确保具体类中的方法始终返回其自身类型的元素,而不是 SomeAbstractType 的另一个实例
  • 我添加了另一种可能性,但它也有缺点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多