Reputation: 1070
This is a beginners OOP question, that probably has many answers, but I have not been able to find them. I will try to ask here in the hope that someone can explain or point me in the right direction.
As an example consider my MWE, where RightTriangle
extends Rectangle
that extends Shapes
. The methode semiPerimeter()
is implemented by calling perimeter()
.
All is well for the Rectangle
, where both perimeter()
and semiPerimeter()
works. The problem is the perimeter()
methode of RightTriangle
which overrides the Rectangle
perimeter()
. When running the test, I get a StackOverflowError, because semiPerimeter()
calls perimeter()
that in turn calls semiPerimeter()
.
Why does the super.semiPerimeter()
call not use the perimeter()
from the rectangle super class?
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
}
}
Upvotes: 0
Views: 82
Reputation: 12819
Why does the
super.semiPerimeter()
call not use theperimeter()
from the rectangle super class?
Because you called it on a rightTriangle
object which has overridden the perimeter()
method. It would make no sense for the call to perimiter()
to call the rectangle
class, as it is a rightTriangle
object. Because of this, the two methods continually call themselves, resulting in a StackOverflowError
Upvotes: 2
Reputation: 380
Here's what's happening:
You call t.perimeter()
, which calls super.semiPerimeter()
-> perimeter()
-> super.semiPerimeter()
etc etc etc.
Sounds like you already know this. I believe that when you extend a class, if you create a method with the same signature as the parent class, you override it, making any calls go to your override method instead of the original. The perimeter
the abstract class calls is implicitly this.perimeter
, and what is this
? It's a rightTriangle
. So when your abstract class sees perimeter
it sees the one you made with rightTriangle
.
Upvotes: 1
Reputation: 8318
Your method (t.perimeter()) does call semiPerimeter
method from Shapes
class, which in turn calls perimeter
from rightTriangle
class again and this repeats.
Note that new rightTriangle()
basically means that return perimeter() / 2
will invoke perimeter
method from rightTriangle
class.
Upvotes: 3