Reputation: 35
So I am trying to write some code for one of my tutorials. The input and expected output is as such:
> Square s = new Square(5);
> s.toString();
< Square with area 25.00 and perimeter 20.00
The following is my code:
abstract class Shape {
protected String shapeName;
public abstract double getArea();
public abstract double getPerimeter();
@Override
public String toString() {
return shapeName + " with area " + String.format("%.2f", getArea()) +
" and perimeter " + String.format("%.2f", getPerimeter());
}
}
class Rectangle extends Shape {
protected double width;
protected double height;
public Rectangle(double width) {
this.shapeName = "Rectangle";
this.width = this.height = width;
}
public Rectangle(double width, double height) {
this.shapeName = "Rectangle";
this.width = width;
this.height = height;
}
public double getArea() {
return width * height;
}
public double getPerimeter() {
return 2 * (width + height);
}
}
class Square extends Rectangle {
public Square(double side) {
this.shapeName = "Square";
this.width = this.height = side;
}
}
The problem is when I try to compile it, this error occurs:
error: no suitable constructor found for Rectangle(no arguments)
public Square(double side) {
^
constructor Rectangle.Rectangle(double) is not applicable
(actual and formal argument lists differ in length)
constructor Rectangle.Rectangle(double,double) is not applicable
(actual and formal argument lists differ in length)
I am unsure about how inheritance works in this case. How could I modify my code such that the input returns the correct output? I presume the error lies solely in the Square class as the code compiles otherwise.
Thanks in advance.
Upvotes: 3
Views: 10338
Reputation: 29680
Just to clarify the error message:
error: no suitable constructor found for Rectangle(no arguments) public Square(double side) { ^ constructor Rectangle.Rectangle(double) is not applicable (actual and formal argument lists differ in length) constructor Rectangle.Rectangle(double,double) is not applicable (actual and formal argument lists differ in length)
The constructor of any subclass (e.g. Square
) must call a constructor of its parent (Rectangle
) since the parent part must also be constructed.
If this constructor is not being supplied by the programmer, that is, not being explicitly called (like in the questions code), the compiler automatically inserts a call to the parameter-less constructor of the parent (like in public Square(...) { super(); ... }
).
In this question the compiler sends an error since the parent (Rectangle
) does not have such a constructor. So a constructor of the parent class must be explicit called in the code, like in (as already answered):
public Square(double side) {
super(side,side); // width == height
...
Upvotes: 1
Reputation: 18578
You have to explicitly invoke the super
constructor in the inheriting class.
And if you want to take @runec 's answer into account (yes, I upvoted it because it is just good), you might want to remove the constructor with just a single parameter from Rectangle
and make the Square
handle a rectangle with 4 equal sides.
public class Rectangle extends Shape {
protected double width;
protected double height;
public Rectangle(double width, double height) {
this.shapeName = "Rectangle";
this.width = width;
this.height = height;
}
public double getArea() {
return width * height;
}
public double getPerimeter() {
return 2 * (width + height);
}
}
Here you have the Square
that takes only one double
parameter:
public class Square extends Rectangle {
public Square(double side) {
super(side, side);
this.shapeName = "Square";
this.width = this.height = side;
}
}
This answer is just for showing complete code, the complete idea comes from @runec.
Upvotes: 0
Reputation: 1737
Design-wise I feel the constructor Rectance( double width ) is un-natural for a rectangle and would remove it. The constructor for the Square should look like this:
public Square(double side) {
super(side,side); // width == height
this.shapeName = "Square";
}
To clarify inheritance even more, you could also replace the line this.shapeName= "Rectangle";
with this.shapeName= getClass().getSimpleName();
and remove this.shapeName = "Square";
from Square
's constructor.
Upvotes: 3