【问题标题】:Java API design: narrow return type in methodsJava API 设计:方法中的窄返回类型
【发布时间】:2013-10-08 19:40:32
【问题描述】:

假设我有一个类型族,我在基类型中定义了一组方法:

interface Foo<T> {
   Foo<T> a();
   Foo<T> b();
   ...
}

Bar 扩展了Foo

interface Bar<T> extends Foo<T> {
   Bar<T> a();
   Bar<T> b();
   ...
}

然后Zee 扩展Bar

interface Zee<T> extends Bar<T> {
   Zee<T> a();
   Zee<T> b();
   ...
}

当我用不同的装饰器实现这个类型族时,我发现我经常写类似的东西

class XBar<T> extends XFoo<T> implements Bar<T> {
   Bar<T> a() {
      return (Bar<T>)super.a();
   }
   Bar<T> b() {
      return (Bar<T>)super.b();
   }
   ...
}

这真的很乏味。我想知道这是 Java API 设计中的正常情况还是我做错了什么,或者有一种聪明的方法可以用一行代码解决常量类型转换?

更新,回答您的 cmets 和响应,是的,方法链是我想在这里实现的一件事。顺便说一句,Java8 中的 BaseStream 类型声明似乎是解决此问题的一个很好的例子。我正在尝试使用这种方法。将在这里更新我的进度。

更新 2,当我有多个继承级别时,BaseStream 方法不起作用。见Java inherited Fluent method return type in multiple level hierarchies

【问题讨论】:

  • 你没有描述XFoo&lt;T&gt;,这没有帮助。如果您能以完整的方式证明问题,那就太好了——您只需要一个方法,我怀疑您也不需要Zee
  • 我建议您将Bar&lt;T&gt;Zee&lt;T&gt; 中的方法一起删除,并让他们使用Foo&lt;T&gt; 中的方法。您当然可以从返回类型为Foo&lt;T&gt; 的方法返回Bar&lt;T&gt;。如果这有什么问题,那么您可能需要多解释一下这些接口和类应该做什么。
  • 在下面查看我的 cmets 以回答 #1

标签: java inheritance types casting api-design


【解决方案1】:

为什么你的子类需要返回子类类型?

Liskov Substitution Principle 声明对象可以在不改变任何属性的情况下被子类型替换,因此如果您正确编码类,则不需要强制转换,特别是如果您只是从 super 返回结果。

当您需要在链接期间访问额外的子类方法时,我能想到的唯一一次有此问题的是方法链接(如builder 模式)......但这应该很少见。

【讨论】:

  • 逻辑协变返回类型没用?
  • @MiserableVariable 协变返回类型必须仍然满足超类的约定,因此它们仍然可以作为超类类型传递而不会出现问题。例如,Float 仍然是 Number,因此如果您不需要 Float 上的额外方法,则可以将其返回为 Number
  • 不确定我是否理解。我的评论是针对您的问题,为什么子类需要返回子类类型。如果没有充分的理由,则不需要协变返回类型。
  • 我只是质疑为什么 OP 显示的这个 particular 对象需要返回子类型而不是一般情况。同样一般情况下,返回类型可以是子类,无需修改接口,因此调用者不知道返回的类型是否是子类。
  • 感谢您的澄清。在我看来,您是在说它们根本不需要,永远都不需要。
猜你喜欢
  • 2018-04-23
  • 2014-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-08
  • 2013-08-19
  • 2012-01-01
  • 1970-01-01
相关资源
最近更新 更多