续《JAVA编程思想》学习备忘(第237页:Reusing Classes)-1
Initializing the base class
...it's essential that the base-class subobject be initialized correctly,and there's only one way to guarantee this:Perform the initialization in the constructor by calling the base-class constructor,which has all the appropritate knowledge and privileges to perform the base-class initialization.
示例:
//:reusing/Cartoon.java
//Constructor calls during inheritance.
import static net.mindview.util.Print.*;
class Art{
Art(){print("Art constructor");}
}
class Drawing extends Art{
Drawing(){print("Drawing constructor");}
}
public class Cartoon extends Drawing{
public Cartoon(){print("Cartoon constructor");}
public static void main(String[] args){
Cartoon x = new Cartoon();
}
}
输出结果:
Art constructor
Drawing constructor
Cartoon constructor
You can see that the construction happens from the base"outward,"so the base class is initialized before the derived-class constructors can access it.Even if you don't create a constructor for Cartoon(),the compiler will synthesize a default constructor for you that calls the base-class constructor.
补充示例:(将最后一个类的构造方法注释掉看看效果)
public class Cartoon extends Drawing{
//public Cartoon(){print("Cartoon constructor");}
public static void main(String[] args){
Cartoon x = new Cartoon();
}
}
输出结果:
Art constructor
Drawing constructor
Constructors with arguments
The preceding example has default constructors:that is, they don't have any arguments.It's easy for the compiler to call these because there's no question about what arguments to pass.If there is no default base-class constructor,or if you want to call a base-class constructor that has arguments,you must explicitly write a call to the base-class constructor using the super keyword and the appropriate argument list:
//:reusing/Chess.java
//Inheritance,constructors and arguments.
import static net.mindview.util.Print.*;
class Game{
Game(int i){
print("Game constructor");
}
}
class BoardGame extends Game{
BoardGame(int i){
super(i);
print("BoardGame constructor");
}
}
public class Chess extends BoardGame{
Chess(){
super(11);
print("Chess constructor");
}
public static void main(String[] args){
Chess x = new Chess();
}
}
输出结果:
Game constructor
BoardGame constructor
Chess constructor
If you don't call the base-class constructor in BoardGame(),the compiler will complain that it can't find a constructor of the form Game().In addition,the call to the base-class constructor must be the first thing you do in the derived-class constructor.(The compiler will remind you if you get it wrong.)
Delegation
A third relationship,which is not directly supported by Java,is called delegation.This is midway between inheritance and composition,because you place a member object in the class you're building(like composition),but at the same time you expose all the methods from the member object in your new class(like inheritance).For example,a spaceship needs a control module:
//:reusing/SpaceShipControls.java
public class SpaceShipControls{
void up(int velocity){}
void down(int velocity){}
void left(int velocity){}
void right(int velocity){}
void forward(int velocity){}
void back(int velocity){}
void turboBoost(){}
}
One way to build a spaceship is to use inheritance:
//:reusing/SpaceShip.java
public class SpaceShip extends SpaceShipControls{
private String name;
public SpaceShip(String name){this.name = name;}
public String toString(){return name;}
public static void main(String[] args){
SpaceShip protector = new SpaceShip("NSEA Protector");
protector.forward(100);
}
}
However,a SpaceShip isn't really"a type of"SpaceShipControls,even if,for example,you"tell"a SpaceShip to go forward().It's more accurate to say that a SpaceShip contains SpaceShipControls,and at the same time all the methods in SpaceShipControls are exposed in a SpaceShip.Delegation solves the dilemma:
关于“Delegation”的示例:
//:reusing/SpaceShipDelegation.java
public class SpaceShipDelegation{
private String name;
private SpaceShipControls controls = new SpaceShipControls();
public SpaceShipDelegation(String name){
this.name = name;
}
//Delegated methods:
public void back(int velocity){
controls.back(velocity);
}
public void down(int velocity){
controls.down(velocity);
}
public void forward(int velocity){
controls.forward(velocity);
}
public void left(int velocity){
controls.left(velocity);
}
public void right(int velocity){
controls.right(velocity);
}
public void turboBoost(){
controls.turboBoost();
}
public void up(int velocity){
controls.up(velocity);
}
public static void main(String[] args){
SpaceShipDelegation protector =
new SpaceShipDelegation("NSEA Protector");
protector.forward(100);
}
}
You can see how the methods are forwarded to the underlying controls object,and the interface is thus the same as it is with inheritance.
(待续)