【问题标题】:Making return type of method implementation more concrete than abstract method使方法实现的返回类型比抽象方法更具体
【发布时间】:2018-04-05 11:19:28
【问题描述】:

考虑这个抽象类

abstract class AbstractBox {
  abstract Object getContent();
}

现在我实现了 StringBox,但可能还有其他 Boxes 实现会返回任何类型的内容,从而阻止我将抽象方法的返回类型变得更加具体:

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

除了让getContent() 声明它会返回一个Object 很明显它会返回一个String,我也可以这样做

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

因此清楚地说明getContent() 将返回什么,并且仍然覆盖抽象方法。

  1. 这个有名字吗?
  2. 它有什么缺点吗?

【问题讨论】:

标签: java abstract-class


【解决方案1】:

重写允许指定协变返回类型,在这里您可以在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();

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

【讨论】:

    【解决方案2】:
    1. 是的,它是“协变返回类型”。

    2. 编译器仍会为StringBox 生成返回Object 的“桥接方法”,因此代码大小会略微增加(并且可能会降低性能,但这应该可以通过 JIT 轻松消除) .

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

    【讨论】:

      【解决方案3】:

      我相信这不是问题。例如,如果您使用抽象类,如果您有

       AbstractBox box;
      

      box.getContent()你会得到一个对象,如果你知道实现就可以进行转换

      如果你使用具体的实现,你会得到字符串(它也是一个对象)。

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

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

      并在实现中将其添加为字符串

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

      我认为这没什么区别,因为您仍然必须使用 StringBox 来了解实现

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-02-24
        • 1970-01-01
        • 2014-01-11
        • 2016-08-13
        • 2013-04-16
        • 2016-12-28
        • 1970-01-01
        相关资源
        最近更新 更多