【问题标题】:Is there any way to specify that the return value of a method in an abstract class should be of the same type as the containing class?有没有办法指定抽象类中方法的返回值应该与包含类的类型相同?
【发布时间】:2014-03-20 16:54:10
【问题描述】:

假设我正在编写一些类来执行简单的数学运算,并且我有一个抽象类JNumber,其中包含一个用于添加另一个数字的方法:

public abstract class JNumber
{
  public abstract JNumber add(JNumber addend);

  // etc.
}

add 的返回值表示this 与参数addend 之和。

现在假设我有一个JNumber 的抽象子类(称为JFieldElement),其中包括一个除法方法(我不能在JNumber 类中使用这个方法,因为你不能除整数,例如)。

public abstract class JFieldElement
  extends JNumber
{
  public abstract JFieldElement div(JFieldElement divisor);
}

现在假设我正在编写一个过程,它将采用扩展 JFieldElement 的某个类的实例 x,y,z 并计算如下表达式:

x / (y + z)

我可以试试:

JNumber w = y.add(z);
JNumber result = x.div(w);

但是,如果这样做,我会得到一个错误 - 因为add 的返回类型是JNumber,我们必须将w 声明为JNumber。但是我们不能对它应用函数div,因为该函数需要接收JFieldElement

如果有某种方法可以指定add 函数应始终返回与调用它的任何类相同类型的值,这将起作用。有没有办法做到这一点?

【问题讨论】:

  • 您说JFieldElementJNumber 的子类。我没看到。
  • 你写了“...因为你不能除整数”。其实你可以。 10 除以 3 是 3,1 是提醒。

标签: java inheritance


【解决方案1】:

我认为泛型应该在这里解决问题:

public abstract class JNumber<N extends JNumber<N>>
{
  public abstract N add(N addend);
  // etc.
}

【讨论】:

  • 谢谢 - 我希望在没有泛型的情况下做到这一点,但这看起来相当干净。您能否解释一下为什么会这样?我已经盯着它看了一会儿,但我仍然不确定JNumber&lt;N extends JNumber&lt;N&gt;&gt; 中发生了什么。
  • 如何子类化这个?是public class JFieldElement extends JNumber&lt;JFieldElement&gt;吗?
  • 是的,这是对这个结构进行子类化的方式。我同意这种表示法可能会令人困惑(它看起来像递归)。你粗略地说:我声明了一个类型 JNumber,我可以像在正文中一样使用它的子类。不确定这是否有意义,抱歉。
  • 好的。我还需要在子类中以某种方式使用泛型吗?
  • 取决于你想要什么。以 public abstract class JFieldElement&lt;F extends JFieldElement&lt;F&gt;&gt; extends JNumber&lt;F&gt; 相同的方式生成 JFieldElement 可能是个好主意,但这取决于您的要求。但是,为了实现您的要求,没有必要这样做。
【解决方案2】:
public <T extends JNumber> T add(T addend);

【讨论】:

  • 这是更好的答案,但它很便宜。如何详细说明为什么会这样?
  • 请您解释一下重写此方法的语法吗?我要写public JFieldElement add(JFieldElement addend)吗?
猜你喜欢
  • 1970-01-01
  • 2013-08-14
  • 1970-01-01
  • 2013-04-16
  • 2014-04-03
  • 2013-07-02
  • 1970-01-01
  • 1970-01-01
  • 2014-11-24
相关资源
最近更新 更多