Java 使方法实现的返回类型比抽象方法更具体
考虑一下这个抽象类Java 使方法实现的返回类型比抽象方法更具体,java,abstract-class,Java,Abstract Class,考虑一下这个抽象类 abstract class AbstractBox { abstract Object getContent(); } 现在,我实现了一个StringBox,但是可能还有其他Boxes实现会返回任何类型的内容,这使我无法使抽象方法的返回类型更加具体: class StringBox extends AbstractBox { @Override Object getContent() { return ""; } } 与其让getContent(
abstract class AbstractBox {
abstract Object getContent();
}
现在,我实现了一个StringBox
,但是可能还有其他Box
es实现会返回任何类型的内容,这使我无法使抽象方法的返回类型更加具体:
class StringBox extends AbstractBox {
@Override
Object getContent() {
return "";
}
}
与其让getContent()
声明它将返回一个对象
,显然它将返回一个字符串
,我还可以这样做
class StringBox extends AbstractBox {
@Override
String getContent() {
return "";
}
}
这样就清楚地说明了getContent()
将返回什么,并且仍然覆盖了抽象方法
重写允许指定协变返回类型,在这里您可以在
StringBox
子类中使用它
此功能从Java 1.5开始提供。从(重点是我的): 8.4.5。方法结果 如果 返回类型是引用类型的概念 返回类型可替换性支持协变返回,即 将返回类型专门化为子类型。 在实践中,如果使用
StringBox
声明的类型操作变量,则类的客户端可以返回更具体的类型,这是一件好事,因为它可以避免降级
例如:
StringBox box = new StringBox();
String boxContent = box.getContent();
但是,如果使用AbstractBox
声明的类型操作变量,则在编译时或运行时不会产生任何副作用,因为客户端仍然希望将对象
作为返回类型:
AbstractBox box = new StringBox();
Object boxContent = box.getContent();
在一般情况下,如果协方差返回能使客户机代码更清晰、更简单(就像没有任何强制转换一样),则应使用协方差返回 重写允许指定一个协变返回类型,在这里您可以在
StringBox
子类中使用它
此功能从Java 1.5开始提供。从(重点是我的): 8.4.5。方法结果 如果 返回类型是引用类型的概念 返回类型可替换性支持协变返回,即 将返回类型专门化为子类型。 在实践中,如果使用
StringBox
声明的类型操作变量,则类的客户端可以返回更具体的类型,这是一件好事,因为它可以避免降级
例如:
StringBox box = new StringBox();
String boxContent = box.getContent();
但是,如果使用AbstractBox
声明的类型操作变量,则在编译时或运行时不会产生任何副作用,因为客户端仍然希望将对象
作为返回类型:
AbstractBox box = new StringBox();
Object boxContent = box.getContent();
在一般情况下,如果协方差返回能使客户机代码更清晰、更简单(就像没有任何强制转换一样),则应使用协方差返回 我相信这不是问题。如果使用抽象类,例如
AbstractBox box;
box.getContent()
您将获得一个对象,如果知道实现,您可以强制转换
如果使用具体的实现,则会得到字符串(也是一个对象)
另一个解决方案是使用泛型方法,例如:
abstract class AbstractBox<T> {
abstract T getContent();
}
抽象类AbstractBox{
抽象T getContent();
}
在实现中,将其添加为字符串
class StringBox extends AbstractBox<String> {
@Override
String getContent() {
return "";
}
}
类StringBox扩展了AbstractBox{
@凌驾
字符串getContent(){
返回“”;
}
}
我认为这没有多大区别,因为您仍然需要使用StringBox来了解实现。我相信这不是问题。如果使用抽象类,例如
AbstractBox box;
box.getContent()
您将获得一个对象,如果知道实现,您可以强制转换
如果使用具体的实现,则会得到字符串(也是一个对象)
另一个解决方案是使用泛型方法,例如:
abstract class AbstractBox<T> {
abstract T getContent();
}
抽象类AbstractBox{
抽象T getContent();
}
在实现中,将其添加为字符串
class StringBox extends AbstractBox<String> {
@Override
String getContent() {
return "";
}
}
类StringBox扩展了AbstractBox{
@凌驾
字符串getContent(){
返回“”;
}
}
我认为这没有多大区别,因为您仍然需要使用StringBox来了解实现
StringBox
生成一个返回Object
的“桥接方法”,因此代码大小略有增加(以及性能的潜在降低,但这应该可以通过JIT轻松消除)StringBox
生成一个返回Object
的“桥接方法”,因此代码大小略有增加(以及性能的潜在降低,但这应该可以通过JIT轻松消除)使用泛型不是更好吗?然后使用
AbstractBox
您就知道它将生成什么类型。请看名称。使用泛型不是更好吗?然后使用AbstractBox
您就知道它将生成什么类型。请参见名称。