使返回类型的方法实现比抽象方法更具体

时间:2018-04-05 11:19:29

标签: java abstract-class

考虑这个抽象类

abstract class AbstractBox {
  abstract Object getContent();
}

现在我实现了StringBox,但可能还有其他Box es实现会返回任何类型的内容,这使我无法使抽象方法的返回类型更具体:< / p>

class StringBox extends AbstractBox {
  @Override
  Object getContent() {
    return "";
  }
}

而不是让getContent()声明它会返回Object,很明显它会返回String,我也可以

class StringBox extends AbstractBox {
  @Override
  String getContent() {
    return "";
  }
}

因此清楚地说明了getContent()将返回的内容并仍然覆盖抽象方法。

  1. 这是否有名字?
  2. 有什么缺点吗?

3 个答案:

答案 0 :(得分:4)

覆盖允许指定协变返回类型,在这里您可以在StringBox子类中使用它。

自Java 1.5起,此功能可用 来自JLS.Chapter 8. Classes(强调是我的):

  

<强> 8.4.5。方法结果

     

...

     

如果相反,则返回类型可能会因为相互覆盖的方法而异   返回类型是引用类型。 的概念   return-type-substitutability支持协变返回,即   将返回类型专门化为子类型。

实际上,如果你使用StringBox声明的类型操作变量,那么类的客户端可以返回更具体的类型,这是一件好事,因为它可以避免向下转换。

例如:

StringBox box = new StringBox();
String boxContent = box.getContent();

但是如果你使用AbstractBox声明的类型操作变量,它在编译时或运行时没有任何副作用,因为客户端期望仍然有Object作为返回类型:

AbstractBox box = new StringBox();
Object boxContent = box.getContent();

一般来说,使用协方差返回应该使用它,如果它使客户端代码更清晰和更简单(没有任何强制转换)。

答案 1 :(得分:2)

  1. 是的,它是“协变返回类型”。

  2. 编译器仍然为Object生成一个“桥接方法”,返回StringBox,因此代码大小略有增加(并且可能会降低性能,但这应该很容易被JIT淘汰。

  3. 正如@khelwood所提到的,你经常想要使用泛型而不是协变返回类型(或者除此之外)。

答案 2 :(得分:0)

我确实认为这不是问题。如果您使用抽象类,例如,如果您有

 AbstractBox box;

box.getContent()您将获得一个对象,如果您了解实现,则可以进行投射

如果您使用具体实现,您将获得String(也是一个对象)。

另一个解决方案是使用泛型方法,例如:

abstract class AbstractBox<T> {
  abstract T getContent();
}

并在实现中将其添加为String

class StringBox extends AbstractBox<String> {
  @Override
  String getContent() {
    return "";
  }
}

我不认为它有很大的不同,因为你仍然必须使用StringBox来了解实现