初始化基本类
由于这儿涉及到两个类——基本类及衍生类,而不再是以前的一个,所以在想象衍生类的功效工具时,大概会发生一些疑惑。从外部看,好像新类拥有与基本类沟通的接口,并且可包括一些特另外要领和字段。但担任并非仅仅简朴地复制基本类的接口了事。建设衍生类的一个工具时,它在个中包括了基本类的一个“子工具”。这个子工具就象我们按照基本类自己建设了它的一个工具。从外部看,基本类的子工具已封装到衍生类的工具里了。
虽然,基本类子工具应该正确地初始化,并且只有一种要领能担保这一点:在构建器中执行初始化,通过挪用基本类构建器,后者有足够的本领和权限来执行对基本类的初始化。在衍生类的构建器中,Java会自动插入对基本类构建器的挪用。下面这个例子向各人展示了对这种三级担任的应用:
//: Cartoon.java // Constructor calls during inheritance class Art { Art() { System.out.println("Art constructor"); } } class Drawing extends Art { Drawing() { System.out.println("Drawing constructor"); } } public class Cartoon extends Drawing { Cartoon() { System.out.println("Cartoon constructor"); } public static void main(String[] args) { Cartoon x = new Cartoon(); } } ///:~
该措施的输出显示了自动挪用:
Art constructor
Drawing constructor
Cartoon constructor
可以看出,构建是在基本类的“外部”举办的,所以基本类会在衍生类会见它之前获得正确的初始化。
纵然没有为Cartoon()建设一个构建器,编译器也会为我们自动合成一个默认构建器,并发出对基本类构建器的挪用。
1. 含有自变量的构建器
上述例子有本身默认的构建器;也就是说,它们不含任何自变量。编译器可以很容易地挪用它们,因为不存在详细通报什么自变量的问题。假如类没有默认的自变量,可能想挪用含有一个自变量的某个基本类构建器,必需明晰地编写对基本类的挪用代码。这是用super要害字以及适当的自变量列表实现的,如下所示:
//: Chess.java // Inheritance, constructors and arguments class Game { Game(int i) { System.out.println("Game constructor"); } } class BoardGame extends Game { BoardGame(int i) { super(i); System.out.println("BoardGame constructor"); } } public class Chess extends BoardGame { Chess() { super(11); System.out.println("Chess constructor"); } public static void main(String[] args) { Chess x = new Chess(); } } ///:~
假如不挪用BoardGames()内的基本类构建器,编译器就会陈诉本身找不到Games()形式的一个构建器。除此以外,在衍生类构建器中,对基本类构建器的挪用是必需做的第一件工作(如操纵失当,编译器会向我们指出)。
2. 捕捉根基构建器的违例
正如适才指出的那样,编译器会强迫我们在衍生类构建器的主体中首先配置对基本类构建器的挪用。这意味着在它之前不能呈现任何对象。正如各人在第9章会看到的那样,这同时也会防备衍生类构建器捕捉来自一个基本类的任何违例事件。显然,这有时会为我们造成未便。