Java: 在调用超类型构造函数之前无法引用高度
Java: cannot reference height before supertype constructor has been called
我正在尝试创建一个 class 图,其中包含矩形、三角形和圆形等子class。然而,当我尝试编译它们时,我在所有这些中都遇到了相同的错误,这让我相信错误在图 class 中。错误:在调用超类型构造函数之前无法引用高度。
图:
public abstract class Figure{
public double width;
public double height;
public Figure(double width, double height){
this.width = width;
this.height = height;
}
public abstract double area();
public abstract double perimeter();
}
椭圆:
public class Ellipse extends Figure{
private double a;
private double b;
public Ellipse(){
a = width/2;
b = height/2;
}
public double area(){
return (Math.PI * a * b);
}
public double perimeter(){
return (2 * Math.PI * Math.sqrt((Math.pow(a,2) + Math.pow(b,2)))/2);
}
}
非常感谢。
您需要初始化您的高度和宽度,它们当前存在于您的图中 class。您可以通过专门从 Ellipse 调用 Figure 构造函数来实现,就像这样。
public Ellipse(){
super(23, 23);
a = width /2;
b = height/2;
}
super() 方法调用您的 Figure 构造函数,然后它将初始化高度和重量,使您可以使用它们相应地计算 a 和 b。
您需要在 Ellipse 中调用超级 class 构造函数:
public Ellipse(){
super(_width, _height)
a = width/2;
b = height/2;
}
您需要在 Figure:
的每个子 class 的每个构造函数中首先调用 super
public Ellipse(double ewidth, double eheight){
super(ewidth, eheight);
a = width/2;
b = height/2;
}
这是必要的,因为您使用 width
和 height
,它们是 Figure
的成员,并且仅在执行 Figure
构造函数时才被初始化,这是 super 调用的作用。您基本上使用了一个未初始化的变量。
那么为什么我调用新参数ewidth而不是width呢?如果我将它们命名为宽度,父 class 中的同名字段将被同名的局部变量遮盖。在您的示例中,这不会成为问题,因为两个构造函数中的代码路径都非常简单,但我想提高人们对此的认识,因为它是隐蔽错误的来源:)
因此您的 Ellipse 构造函数不会调用 Figure 的继承构造函数。然而,您正在尝试使用在 Figure 的构造函数中赋值的 Figure 变量。您需要更新 Ellipse 构造函数以使用值调用 super。我推荐以下。
public Ellipse(int w, int h){
super(w,h);
a = width / 2;
b = width / 2;
}
每个class都必须调用它的superclass的构造函数作为它自己的每个构造函数中的第一条指令[1]
如果 superclass 有一个默认的构造函数(一个没有参数的构造函数),这是隐式完成的。但是如果它只有一个带参数的构造函数,那么你必须自己编写那个调用。您可以通过使用单词 super
并传递适当的参数来做到这一点。
这样做是为了能够正确初始化当前 class 中继承自 superclass 的逻辑部分。
您有两种可能的解决方案:
将默认构造函数添加到 Figure
。也许默认宽度和高度为零:
public Figure() {
this( 0.0, 0.0 );
}
如果宽度和高度有一个合理的默认值,这就有意义了。
更改子classes 的构造函数,以便它们也接受(至少)宽度和高度:
public Ellipse(double width, double height){
super(width, height);
a = width/2;
b = height/2;
}
如果没有合理的宽度和高度默认值,这是有道理的。
按照您尝试这样做的方式,将没有宽度和高度值,因此您不可能在 subclass 中使用它们(例如 width/2
将为零,因为没有任何东西可以在 width
中放置任何值,因为没有人调用 Figure
的构造函数)。当你创建一个实例时,没有其他地方会调用设置 width
和 height
的 superclass 构造函数 - 因此所有构造函数都必须首先调用它们的 superclass 构造函数优先。
[1] 也可以调用同一个 class 的其他构造函数之一 - 如果它有多个 - 前提是最终被调用的构造函数调用 supeclass 构造函数。
类似的问题已经有人回答了。
参考这个:
java call superclass from a subclass constructor?
要补充一点,如果你的 superclass 中有一个非参数化的构造函数,那么你就不必显式调用 superclass.[=12 的构造函数=]
同时检查一下:https://docs.oracle.com/javase/tutorial/java/IandI/super.html
此页面上有一条注释:如果构造函数没有显式调用 superclass 构造函数,Java 编译器会自动插入对 super[ 的无参数构造函数的调用=21=]。如果 super class 没有无参数构造函数,您将得到编译时错误。 Object确实有这样一个构造函数,所以如果Object是唯一的superclass,没有问题。
我正在尝试创建一个 class 图,其中包含矩形、三角形和圆形等子class。然而,当我尝试编译它们时,我在所有这些中都遇到了相同的错误,这让我相信错误在图 class 中。错误:在调用超类型构造函数之前无法引用高度。
图:
public abstract class Figure{
public double width;
public double height;
public Figure(double width, double height){
this.width = width;
this.height = height;
}
public abstract double area();
public abstract double perimeter();
}
椭圆:
public class Ellipse extends Figure{
private double a;
private double b;
public Ellipse(){
a = width/2;
b = height/2;
}
public double area(){
return (Math.PI * a * b);
}
public double perimeter(){
return (2 * Math.PI * Math.sqrt((Math.pow(a,2) + Math.pow(b,2)))/2);
}
}
非常感谢。
您需要初始化您的高度和宽度,它们当前存在于您的图中 class。您可以通过专门从 Ellipse 调用 Figure 构造函数来实现,就像这样。
public Ellipse(){
super(23, 23);
a = width /2;
b = height/2;
}
super() 方法调用您的 Figure 构造函数,然后它将初始化高度和重量,使您可以使用它们相应地计算 a 和 b。
您需要在 Ellipse 中调用超级 class 构造函数:
public Ellipse(){
super(_width, _height)
a = width/2;
b = height/2;
}
您需要在 Figure:
super
public Ellipse(double ewidth, double eheight){
super(ewidth, eheight);
a = width/2;
b = height/2;
}
这是必要的,因为您使用 width
和 height
,它们是 Figure
的成员,并且仅在执行 Figure
构造函数时才被初始化,这是 super 调用的作用。您基本上使用了一个未初始化的变量。
那么为什么我调用新参数ewidth而不是width呢?如果我将它们命名为宽度,父 class 中的同名字段将被同名的局部变量遮盖。在您的示例中,这不会成为问题,因为两个构造函数中的代码路径都非常简单,但我想提高人们对此的认识,因为它是隐蔽错误的来源:)
因此您的 Ellipse 构造函数不会调用 Figure 的继承构造函数。然而,您正在尝试使用在 Figure 的构造函数中赋值的 Figure 变量。您需要更新 Ellipse 构造函数以使用值调用 super。我推荐以下。
public Ellipse(int w, int h){
super(w,h);
a = width / 2;
b = width / 2;
}
每个class都必须调用它的superclass的构造函数作为它自己的每个构造函数中的第一条指令[1]
如果 superclass 有一个默认的构造函数(一个没有参数的构造函数),这是隐式完成的。但是如果它只有一个带参数的构造函数,那么你必须自己编写那个调用。您可以通过使用单词 super
并传递适当的参数来做到这一点。
这样做是为了能够正确初始化当前 class 中继承自 superclass 的逻辑部分。
您有两种可能的解决方案:
将默认构造函数添加到
Figure
。也许默认宽度和高度为零:public Figure() { this( 0.0, 0.0 ); }
如果宽度和高度有一个合理的默认值,这就有意义了。
更改子classes 的构造函数,以便它们也接受(至少)宽度和高度:
public Ellipse(double width, double height){ super(width, height); a = width/2; b = height/2; }
如果没有合理的宽度和高度默认值,这是有道理的。
按照您尝试这样做的方式,将没有宽度和高度值,因此您不可能在 subclass 中使用它们(例如 width/2
将为零,因为没有任何东西可以在 width
中放置任何值,因为没有人调用 Figure
的构造函数)。当你创建一个实例时,没有其他地方会调用设置 width
和 height
的 superclass 构造函数 - 因此所有构造函数都必须首先调用它们的 superclass 构造函数优先。
[1] 也可以调用同一个 class 的其他构造函数之一 - 如果它有多个 - 前提是最终被调用的构造函数调用 supeclass 构造函数。
类似的问题已经有人回答了。 参考这个: java call superclass from a subclass constructor?
要补充一点,如果你的 superclass 中有一个非参数化的构造函数,那么你就不必显式调用 superclass.[=12 的构造函数=]
同时检查一下:https://docs.oracle.com/javase/tutorial/java/IandI/super.html
此页面上有一条注释:如果构造函数没有显式调用 superclass 构造函数,Java 编译器会自动插入对 super[ 的无参数构造函数的调用=21=]。如果 super class 没有无参数构造函数,您将得到编译时错误。 Object确实有这样一个构造函数,所以如果Object是唯一的superclass,没有问题。