【发布时间】:2018-10-16 17:42:13
【问题描述】:
这是一个初学者 OOP 问题,可能有很多答案,但我一直没能找到它们。我会尝试在这里提问,希望有人可以解释或指出我正确的方向。
以我的 MWE 为例,其中 RightTriangle 扩展 Rectangle 扩展 Shapes。方法semiPerimeter()是通过调用perimeter()实现的。
Rectangle 一切顺利,perimeter() 和 semiPerimeter() 都可以使用。问题是RightTriangle 的perimeter() 方法覆盖了Rectangle perimeter()。运行测试时,我收到 StackOverflowError,因为 semiPerimeter() 调用 perimeter() 又调用 semiPerimeter()。
为什么super.semiPerimeter() 调用不使用矩形超类中的perimeter()?
MWE
Shapes.java
package ShapesPackage;
public abstract class Shapes {
public abstract double perimeter();
public double semiPerimeter() {
return perimeter() / 2;
}
}
Rectangle.java
package ShapesPackage;
public class Rectangle extends Shapes {
public double perimeter() {
return 2 * (3 + 4); //2*(length+height)
}
}
RightTriangle.java
package ShapesPackage;
public class RightTriangle extends Rectangle {
public double perimeter() {
return super.semiPerimeter() + 5; //half the rectangle perimeter plus some hypotenuse
}
}
Test.java
package ShapesPackage;
public class Test {
public static void main(String[] args) {
Rectangle r = new rectangle();
System.out.println(r.perimeter());
System.out.println(r.semiPerimeter());
RightTriangle t = new rightTriangle();
System.out.println(t.perimeter()); //Fails
}
}
【问题讨论】:
-
它确实使用了
super.semiPermiter()方法。但是那个调用this.permiter()作为回报(它总是指向最孩子的实现)。从而开始一个无限循环。将调用更改为Rectangle.this.permiter()将解决问题(因为它专门调用 Rectangles 的实现) -
半周界法中没有基本情况。
-
因为 rightTriangle 覆盖 perimiter() 所以 triangle.perimeter() --> super(Shapes).semiPermiator() --> triangle.perimiter() 这是递归调用,没有办法结束。另外,请遵循标准的 java 命名约定。另外,rightTriangle 扩展 (is-a) 矩形是否有意义?
-
@Sam Orozco:你的意思是 base case 吗? - 它用于递归调用!我试图避免所有递归调用。
-
@Andrew S:你是对的 - 为矩形形式调用 rightTriangle 是愚蠢的,但我被要求以这种方式进行练习。我猜创作者正在寻找一个多重扩展的例子。