开课吧课堂之如何创建多级类层次

125 阅读3分钟

到目前分享的文章,我们会发现,我们已经用到了只含有一个超类和一个子类的简单类层次结构。然而,你可以如你所愿的建立包含任意多层继承的类层次。

前面提到,用一个子类作为另一个类的超类是完全可以接受的。例如,给定三个类A,B和C。C是B的一个子类,而B又是A的一个子类。当这种类型的情形发生时,每个子类继承它的所有超类的属性。

这种情况下,C继承B和A的所有方面。为了理解多级层次的用途,考虑下面的程序。该程序中,子类BoxWeight用作超类来创建一个名为Shipment的子类。Shipment继承了BoxWeight和Box的所有特征,并且增加了一个名为cost的成员,该成员记录了运送这样一个小包的费用。

// Extend BoxWeight to include shipping costs. 
// Start with Box. 
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; 
 } 
} 
// Add weight. 
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; 
 } 
} 
// Add shipping costs 
class Shipment extends BoxWeight { 
 double cost; 
 // construct clone of an object 
 Shipment(Shipment ob) { // pass object to constructor 
 super(ob); 
 cost = ob.cost; 
 } 
 // constructor when all parameters are specified 
 Shipment(double w, double h, double d, 
 double m, double c) { 
 super(w, h, d, m); // call superclass constructor 
 cost = c; 
 } 
 // default constructor 
 Shipment() { 
 super(); 
 cost = -1; 
 } 
 // constructor used when cube is created 
 Shipment(double len, double m, double c) { 
 super(len, m); 
 cost = c; 
 } 
} 
class DemoShipment { 
 public static void main(String args[]) { 
 Shipment shipment1 = 
 new Shipment(10, 20, 15, 10, 3.41); 
 Shipment shipment2 = 
 new Shipment(2, 3, 4, 0.76, 1.28); 
 double vol; 
 vol = shipment1.volume(); 
 System.out.println("Volume of shipment1 is " + vol); 
 System.out.println("Weight of shipment1 is " 
 + shipment1.weight); 
 System.out.println("Shipping cost: $" + shipment1.cost); 
 System.out.println(); 
 vol = shipment2.volume(); 
 System.out.println("Volume of shipment2 is " + vol); 
 System.out.println("Weight of shipment2 is " 
 + shipment2.weight); 
 System.out.println("Shipping cost: $" + shipment2.cost); 
 } 
}

下面是该程序的输出:

Volume of shipment1 is 3000.0 
Weight of shipment1 is 10.0 
Shipping cost: $3.41 
Volume of shipment2 is 24.0 
Weight of shipment2 is 0.76 
Shipping cost: $1.28

因为继承关系,Shipment可以利用原先定义好的Box和BoxWeight类,仅为自己增加特殊用途的其他信息。这体现了继承的部分价值;它允许代码重用。

该例阐述了另一个重要的知识点:super( )总是引用子类最接近的超类的构造函数。Shipment中super( )调用了BoxWeight的构造函数。BoxWeight中的super( )调用了Box中的构造函数。在类层次结构中,如果超类构造函数需要参数,那么不论子类它自己需不需要参数,所有子类必须向上传递这些参数。

Java中所有三个类可以被放置在它们自己的文件中且可以独立编译。实际上,在创建类层次结构的时候,使用分离的文件是常见的,不是罕见的。