“扩展”实际上是做什么的?

时间:2019-06-21 08:24:36

标签: java constructor abstract extends

我目前正在研究“类抽象”和“扩展”的概念,一直想知道:
“如果我在抽象类中声明了参数化的构造函数,那么除非我用super关键字声明自己的构造函数并调用抽象类的构造函数的参数,否则为什么不能在另一个类上进行扩展?”

我了解以下事实:扩展将先前的抽象类实例化为扩展类,并尝试调用默认构造函数,但一直想知道为什么会给出错误。

是因为构造函数已参数化,还是仅仅是因为空的构造函数不存在?

扩展关键字是否按此方式调用某些内容?

Object myClass = new AbstractClass();

缺少参数是它发出错误的原因,因此类似的内容将是正确的

Object myClass = new AbstractClass(int foo,float boo);

如果是这样的话,super关键字在本质上是否有用?如果您允许我使用术语,则将括号中给出的参数“放入”构造函数内部?

如果不是,那我要怎么做? 实际上如何工作?

4 个答案:

答案 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();