从Box派生的类并没有体现出它们的实际上是多么有效和强大。例如,BoxWeight构造函数明确的初始化了Box( )的width、height和depth成员。
这些重复的代码在它的超类中已经存在,这样做效率很低,而且,这意味着子类必须被同意具有访问这些成员的权力。然而,有时你希望创建一个超类,该超类可以保持它自己实现的细节(也就是说,它保持私有的数据成员)。这种情况下,子类没有办法直接访问或初始化它自己的这些变量。既然封装是面向对象的基本属性,Java提供了该问题的解决方案是不值得奇怪的。
任何时候一个子类需要引用它直接的超类,它可以用关键字super来实现。super有两种通用形式。第一种调用超类的构造函数。第二种用来访问被子类的成员隐藏的超类成员。下面分别介绍每一种用法(第二种下个文章中介绍)。
使用super调用超类构造函数子类可以调用超类中定义的构造函数方法,用super的下面形式:java
复制代码super(parameter-list);
这里,parameter-list定义了超类中构造函数所用到的所有参数。super( )必须是在子类构造函数中的第一个执行语句。为了了解怎样运用super( ),考虑下面BoxWeight( )的改进版本:java
复制代码// BoxWeight now uses super to initialize its Box attributes.
class BoxWeight extends Box {
double weight; // weight of box
// initialize width, height, and depth using super()
BoxWeight(double w, double h, double d, double m) {
super(w, h, d); // call superclass constructor
weight = m;
}
}
这里,BoxWeight( )调用带w、h和d参数的super( )方法。这使Box( )构造函数被调用,用w、h和d来初始化width, height, 和 depth。BoxWeight不再自己初始化这些值。它只需初始化它自己的特殊值:weight。这种方法使Box可以自由的根据需要把这些值声明成private。
上面的例子,调用super( )用了三个参数。既然构造函数可以被重载,可以用超类定义的任何形式调用super( ),执行的构造函数将是与所传参数相匹配的那一个。
例如,下面是BoxWeight一个完整的实现,BoxWeight具有以不同方法构造盒子的构造函数。在每种情况下,用适当的参数调用super( )。注意width, height, and depth在Box是私有的。java
复制代码// A complete implementation of BoxWeight.
class Box {
private double width;
private double height;
private double depth;
// construct clone of an object
Box(Box ob) { // pass object to constructor
width = ob.width;
height = ob.height;
depth = ob.depth;
}
// constructor used when all dimensions specified
Box(double w, double h, double d) {
width = w;
height = h;
depth = d;
}
// constructor used when no dimensions specified
Box() {
width = -1; // use -1 to indicate
height = -1; // an uninitialized
depth = -1; // box
}
// constructor used when cube is created
Box(double len) {
width = height = depth = len;
}
// compute and return volume
double volume() {
return width * height * depth;
}
}
// BoxWeight now fully implements all constructors.
class BoxWeight extends Box {
double weight; // weight of box
// construct clone of an object
BoxWeight(BoxWeight ob) { // pass object to constructor
super(ob);
weight = ob.weight;
}
// constructor when all parameters are specified
BoxWeight(double w, double h, double d, double m) {
super(w, h, d); // call superclass constructor
weight = m;
}
// default constructor
BoxWeight() {
super();
weight = -1;
}
// constructor used when cube is created
BoxWeight(double len, double m) {
super(len);
weight = m;
}
}
class DemoSuper {
public static void main(String args[]) {
BoxWeight mybox1 = new BoxWeight(10, 20, 15, 34.3);
BoxWeight mybox2 = new BoxWeight(2, 3, 4, 0.076);
BoxWeight mybox3 = new BoxWeight(); // default
BoxWeight mycube = new BoxWeight(3, 2);
BoxWeight myclone = new BoxWeight(mybox1);
double vol;
vol = mybox1.volume();
System.out.println("Volume of mybox1 is " + vol);
System.out.println("Weight of mybox1 is " + mybox1.weight);
System.out.println();
vol = mybox2.volume();
System.out.println("Volume of mybox2 is " + vol);
System.out.println("Weight of mybox2 is " + mybox2.weight);
System.out.println();
vol = mybox3.volume();
System.out.println("Volume of mybox3 is " + vol);
System.out.println("Weight of mybox3 is " + mybox3.weight);
System.out.println();
vol = myclone.volume();
System.out.println("Volume of myclone is " + vol);
System.out.println("Weight of myclone is " + myclone.weight);
System.out.println();
vol = mycube.volume();
System.out.println("Volume of mycube is " + vol);
System.out.println("Weight of mycube is " + mycube.weight);
System.out.println();
}
}
该程序产生下面的输出:java
复制代码Volume of mybox1 is 3000.0
Weight of mybox1 is 34.3
Volume of mybox2 is 24.0
Weight of mybox2 is 0.076
Volume of mybox3 is -1.0
Weight of mybox3 is -1.0
Volume of myclone is 3000.0
Weight of myclone is 34.3
Volume of mycube is 27.0
Weight of mycube is 2.0
特别注意BoxWeight( )中的这个构造函数:java
复制代码// construct clone of an object
BoxWeight(BoxWeight ob) { // pass object to constructor
super(ob);
weight = ob.weight;
}
注意super( )被用一个BoxWeight类型而不是Box类型的对象调用。这仍然调用了构造函数Box(Box ob)。前面已经提醒过,一个超类变量可以引用作为任何一个从它派生的对象。
因此,我们可以传递一个BoxWeight对象给Box构造函数。当然,Box只知道它自己成员的信息。
让我们复习super( )中的关键概念。当一个子类调用super( ),它调用它的直接超类的构造函数。这样,super( )总是引用调用类直接的超类。这甚至在多层次结构中也是成立的。
还有,super( )必须是子类构造函数中的第一个执行语句。