我目前正在研究“类抽象”和“扩展”的概念,一直想知道:
“如果我在抽象类中声明了参数化的构造函数,那么除非我用super关键字声明自己的构造函数并调用抽象类的构造函数的参数,否则为什么不能在另一个类上进行扩展?”
我了解以下事实:扩展将先前的抽象类实例化为扩展类,并尝试调用默认构造函数,但一直想知道为什么会给出错误。
是因为构造函数已参数化,还是仅仅是因为空的构造函数不存在?
扩展关键字是否按此方式调用某些内容?
Object myClass = new AbstractClass();
缺少参数是它发出错误的原因,因此类似的内容将是正确的
Object myClass = new AbstractClass(int foo,float boo);
如果是这样的话,super
关键字在本质上是否有用?如果您允许我使用术语,则将括号中给出的参数“放入”构造函数内部?
如果不是,那我要怎么做? 实际上如何工作?
答案 0 :(得分:2)
在这种情况下,您应该想到extends
关键字,就像在说一个类是另一个类的子类,什么也不做。并且有规则来控制子类和超类的工作方式。
构造子类时,必须首先构造其超类。例如,要创建Bird
,必须首先创建Animal
。那有意义吗?为了在代码中演示这一点:
class Animal {
public Animal() {
System.out.println("Animal");
}
}
class Bird extends Animal {
public Bird() {
System.out.println("Bird");
}
}
执行new Bird()
将首先打印Animal
,然后打印Bird
,因为先调用Animal
的构造函数,然后再调用Bird
构造函数。因此,实际上,Bird
构造函数隐式调用了超类的构造函数。可以这样写:
public Bird() {
super();
System.out.println("Bird");
}
现在,如果超类没有无参数构造函数,会发生什么?假设Animal
的构造函数现在以String name
作为参数。您仍然需要先调用超类的构造函数,但是super()
无效,因为super()
需要一个字符串参数!
因此,编译器会给您一个错误。可以通过使用参数调用super()
显式 来解决此问题。
答案 1 :(得分:1)
“如果我在抽象类中声明了参数化的构造函数,为什么 除非我宣布自己是 带有super关键字的构造函数,调用 抽象类的构造函数?”
因为超类说它必须是使用声明的构造函数的构造函数,并且没有其他方法可以解决。这适用于每个扩展类-必须调用必需的构造函数。
当您声明除默认构造函数以外的其他构造函数时,任何类都会发生相同的情况。例如,拥有
public class A{
//no default no-arg ctor here
public A(String name){
....
}
}
public class B{
//default no-arg ctor will be created
}
那么
B b=new B();
A a=new A(); //// INVALID!
A a=new A("foobar"); // yeah that is it
扩展类时同样如此。要构造子实例,必须首先“内部创建父实例”,调用super.constructor
。由于没有默认构造函数,因此必须使用任何显式声明的超级构造函数。
答案 2 :(得分:0)
初始化对象时,将始终调用构造函数。即使您没有定义一个构造函数,也会有一个默认的没有任何参数的构造函数。因此,如果您在抽象类中定义了一个构造函数,则必须使用super()
来调用该构造函数。
如果未定义任何构造函数,则将其隐式调用为默认构造函数。
答案 3 :(得分:0)
如果我在抽象类中声明了参数化的构造函数,为什么除非我用super关键字声明自己的构造函数并调用抽象类的构造函数的参数,否则不能在另一个类上进行扩展?
AbstractClass
中没有默认的构造函数,因为您定义了参数化的构造函数。如果您自己没有定义构造函数,则会隐式创建一个没有参数的默认构造函数。您可以立即手动添加此类,或者需要将{strong> only 可用的构造函数(已参数化)与super()
一起使用。
具有不带参数的定义构造函数的代码示例:
class AbstractClass {
AbstractClass() {} // added manually since not created implicitly
AbstractClass(int foo, float boo) {}
}
class RealClass extends AbstractClass {
RealClass() { } // calls super() implicitly
}
AbstractClass myClass = new RealClass();
使用参数调用super()
的代码示例:
class RealClass extends AbstractClass {
RealClass() {
super(1, 2);
}
}
class AbstractClass {
AbstractClass(int foo, float boo) {}
}
AbstractClass myClass = new RealClass();