有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java我想要一个函数返回调用它的子类的实例

我想在超类中定义一个函数,该超类返回用于调用该函数的子类的实例。也就是说,假设我有一个带有函数plugh的类A。然后我创建扩展A的子类B和C。我希望B.plugh返回一个B,C.plugh返回一个C。是的,他们可以返回一个A,但是调用者必须要么将其转换为正确的子类型,这在频繁使用时是一种痛苦,要么将接收变量声明为超类型,这将失去类型安全性

所以我试着用泛型来做这件事,写了这样的东西:

class A<T extends A>
{
  private T foo;
  public T getFoo()
  {
    return foo;
  }
}
class B extends A<B>
{
  public void calcFoo()
  {
    foo=... whatever ...
  } 
}
class C extends A<C>
{
   public void calcFoo()
  {
    foo=... whatever ...
  } 
}

这似乎管用,但看起来很难看

首先,我在class A<T extends A>上收到警告。编译器说A是泛型的,我应该指定类型。我猜它想让我说class A<T extends A<x>。但我会为x投什么呢?我想我可能会陷入无限循环

class B extends A<B>似乎很奇怪,但这不会引起任何抱怨,所以也许这很好

这样做对吗?有更好的办法吗


共 (2) 个答案

  1. # 1 楼答案

    class A<T extends A<T>> {
    

    或者,我更喜欢:

    class A<THIS extends A<THIS>> {
    

    比如java.lang.Enum。它使只需要A但必须编写A<?>的客户机代码变得丑陋

    注意,这不会以任何方式破坏LSP,这是一个好的OO

    或者你可以使用协变返回类型

  2. # 2 楼答案

    从严格的OO角度来看,这样做是一件非常糟糕的事情™. 它违反了Liskov Substitution Principle换一个——如果B&;C都是A,那么B.getFoo()和C.getFoo()应该返回相同的结果——在本例中,它们不会返回相同的结果。如果调用方需要知道调用该方法时得到了什么,那么很可能您的继承层次结构是错误的