构造函数和继承
我想知道如何在子类中使用超类构造函数,但需要在子类中实例化更少的属性。下面是两个班。我甚至不确定我目前是否在做正确的事情。在第二个类中,有一个错误提示“隐式超级构造函数PropertyDB()未定义,必须显式调用另一个构造函数。”请注意,此代码显然不完整,并且有代码被注释掉。构造函数和继承
public abstract class PropertyDB {
private int hectares;
private String crop;
private int lotWidth;
private int lotDepth;
private int buildingCoverage;
private int lakeFrontage;
private int numBedrooms;
private int listPrice;
//public abstract int getPricePerArea();
//public abstract int getPricePerBuildingArea();
public PropertyDB(int newHectares, String newCrop, int newLotWidth, int newLotDepth,
int newBuildingCoverage, int newLakeFrontage, int newNumBedrooms, int newListPrice){
hectares = newHectares;
crop = newCrop;
lotWidth = newLotWidth;
lotDepth = newLotDepth;
buildingCoverage = newBuildingCoverage;
lakeFrontage = newLakeFrontage;
numBedrooms = newNumBedrooms;
listPrice = newListPrice;
}
}
public class FarmedLand extends PropertyDB{
public FarmedLand(int newHectares, int newListPrice, String newCorn){
//super(270, 100, "corn");
hectares = newHectares;
listPrice = newListPrice;
corn = newCorn;
}
}
隐式构造函数PropertyDB()
仅当您未定义任何其他构造函数时才存在,在这种情况下,您将不得不明确定义PropertyDB()
构造函数。
您看到此错误的原因“隐式超级构造函数PropertyDB()未定义,必须显式调用另一个构造函数。在您的public FarmedLand(int newHectares, int newListPrice, String newCorn)
构造函数中,super()
将自动作为第一条语句进行调用,该语句在您的超类中不存在。
下面是一个简化的例子:
public class A { }
可以通过使用A a = new A()
被实例化,因为public A() { }
是类A的一个隐式构造
public class A {
public A(int z) { /* do nothing*/ }
}
可以不使用A a = new A()
因为通过定义实例化的一个明确的构造函数public A(int z)
隐式的不再可用。
移动到构造函数和继承,从Java Language Specification section 8.8.7:
如果构造体不明确的构造函数调用,并正在申报的构造开始不是原始类对象的一部分,那么构造体由编译器隐含地假定以超类构造函数调用“super();”开头,该超类构造函数调用其直接超类的构造函数的调用,其不带任何参数。
所以你的情况在public FarmedLand(int newHectares, int newListPrice, String newCorn)
构造函数中执行的第一个语句是隐式调用,而你的情况是不是隐含定义(不过已经有了public PropertyDB(int, String, ...)
构造函数中定义)或明确(它不是在源代码中)
你看到的错误是由于事实PropertyDB
类没有一个默认的(无参数)构造函数。可以在PropertyDB
中创建它,或者使用super
从FarmedLand
构造函数中调用现有的超类构造函数PropertyDB(int newHectares, String newCrop, int newLotWidth, int newLotDepth, int newBuildingCoverage, int newLakeFrontage, int newNumBedrooms, int newListPrice)
。
改为使用super(newHectares, newCorn, 0, 0, 0, 0, newListPrice);
。无论如何,0是int
的默认值。
我早先想到了这个解决方案,但如果我不想将任何属性设置为0或null,我该怎么做呢? – 2012-03-09 03:27:53
@ProgrammingKeener该类的每个字段都应该有一个值。 – 2012-03-09 03:29:02
如果不明确设置属性,Java会为您设置它们 - 数字类型为'0',布尔值为'false',对象类型为'null' – 2012-03-09 03:29:36
你的超类只有一个构造函数,所以你的子类构造函数必须调用它。这是没有办法的:超类具有(例如)lotWidth
字段,所以子类必须具有该字段,并且超类在其构造函数中初始化该字段,所以它必须在子类中初始化。
因此,除非以某种方式修改超类,否则必须调用super(...)
作为子类构造函数中的第一件事,为其所有参数指定值。
当你有一个派生类extends
的基类,基类始终构造派生类之前。如果你没有明确指定基类使用哪个构造函数(如你的例子),Java假定你的意思是无参数构造函数(在你的情况下是PropertyDB()
的构造函数)。
但等 - PropertyDB
没有无参数的构造函数!所以你唯一的选择是使用super
,以便Java编译器知道哪个构造函数要调用基类。在你的情况下,只有一个构造函数可供选择,所以你必须使用它的所有8个参数。如果您想使用较少的参数,则必须指定“默认”值(例如,通过0
),否则定义更多构造函数用于参数较少的PropertyDB
。
我仍然是初学者,但这似乎很有帮助。你能详细解释一下吗? – 2012-03-09 03:30:02