这是一个初学者的OOP问题,可能有很多答案,但我一直找不到。我将尝试在这里提出要求,希望有人可以向我解释或指出正确的方向。
以我的MWE为例,其中RightTriangle
扩展了Rectangle
,扩展了Shapes
。方法semiPerimeter()
是通过调用perimeter()
来实现的。
Rectangle
和perimeter()
都可以正常工作的semiPerimeter()
一切都很好。问题是perimeter()
的{{1}}方法覆盖了RightTriangle
Rectangle
。运行测试时,我收到一个StackOverflowError,因为perimeter()
调用semiPerimeter()
,而后者依次调用perimeter()
。
为什么semiPerimeter()
调用不使用矩形超类中的super.semiPerimeter()
?
Shapes.java
perimeter()
Rectangle.java
package ShapesPackage;
public abstract class Shapes {
public abstract double perimeter();
public double semiPerimeter() {
return perimeter() / 2;
}
}
RightTriangle.java
package ShapesPackage;
public class Rectangle extends Shapes {
public double perimeter() {
return 2 * (3 + 4); //2*(length+height)
}
}
Test.java
package ShapesPackage;
public class RightTriangle extends Rectangle {
public double perimeter() {
return super.semiPerimeter() + 5; //half the rectangle perimeter plus some hypotenuse
}
}
答案 0 :(得分:3)
您的方法(t.perimeter())确实从semiPerimeter
类调用了Shapes
方法,而该方法又从perimeter
类调用了rightTriangle
并且重复了。 / p>
请注意,new rightTriangle()
基本上意味着return perimeter() / 2
将调用perimeter
类中的rightTriangle
方法。
答案 1 :(得分:2)
为什么
super.semiPerimeter()
调用不使用矩形超类中的perimeter()
?
因为您在覆盖rightTriangle
方法的perimeter()
对象上调用了它。调用perimiter()
调用rectangle
类是没有意义的,因为它是rightTriangle
对象。因此,这两种方法会不断调用自己,从而导致StackOverflowError
答案 2 :(得分:1)
这是正在发生的事情
您呼叫t.perimeter()
,后者呼叫super.semiPerimeter()
-> perimeter()
-> super.semiPerimeter()
等,等等。
像您这样的声音已经知道了。我相信,在扩展类时,如果创建一个与父类具有相同签名的方法,则将其覆盖,从而使所有调用都转到覆盖方法,而不是原始方法。抽象类调用的perimeter
是隐式this.perimeter
,this
是什么?这是rightTriangle
。因此,当您的抽象类看到perimeter
时,就会看到您用rightTriangle
制作的那个。