一、繼承的基礎
在Java術語中,被繼承的類叫超類(superclass)或者父類,繼承超類的類叫子類(subclass).
舉例說明:
1 class Box 2 { 3 public double width; 4 public double height; 5 public double depth; 6 7 //重載構造方法 8 public Box(Box ob) 9 {10 width = ob.width;11 height = ob.height;12 depth = ob.depth;13 }14 15 public Box(double w, double h, double d)16 {17 width = w;18 height = h;19 depth = d;20 }21 22 public Box()23 {24 width = -1;25 height = -1;26 depth = -1;27 }28 29 public Box(double len)30 {31 width = height = depth = len;32 }33 34 //計算體積35 public double volume()36 {37 return width * height * depth;38 }39 }40 41 //下面的類繼承自類Box42 class BoxWeight extends Box43 {44 double weight;45 46 //BoxWeight的構造方法47 BoxWeight (double w, double h, double d, double m)48 {49 width = w;50 height = h;51 depth = d;52 weight = m;53 }54 }55 56 public class DemoBoxWeight57 {58 public static void main(String args[])59 {60 BoxWeight mybox1 = new BoxWeight(10, 20, 15, 34.3);61 BoxWeight mybox2 = new BoxWeight(2, 3, 4, 0.076);62 double vol;63 64 vol = mybox1.volume();65 System.out.如42行所示,聲明一個繼承超類的類,需要用到關鍵字extends,形式如下:
class subclass-name extends superclass-name { // body of class }子類BoxWeight包括超類Box所有成員,這就是為什么在49-51行中子類可以直接給超類的成員賦值,并且子類對象mybox1可以調用超類方法volume()的原因。而且一個子類可以是另一個類的超類。
但是一個子類只允許有一個超類(這與C++不同,C++中派生類可以繼承多個基礎類),任何類不能成為自己的超類。
運行結果:
繼承的一個主要優勢在于一旦你已經創建了一個超類,而該超類定義了適用于一組對象的屬性,它可用來創建任何數量的說明更多細節的子類。每一個子類能夠正好制作它自己的分類。上面的BoxWeight類繼承了Box并增加了一個重量屬性。每一個子類只增添它自己獨特的屬性。
二、成員的訪問權限和繼承
盡管子類包括超類的所有成員,但是它不能訪問超類中被聲明成private的成員,一個被類定義成private的類成員為此類私有,它不能被該類外的所有代碼訪問。
類成員的訪問控制通常有四種public,protected,default,private,下圖對各種控制模式的允許訪問范圍作一個總結:
三、超類變量可以引用子類對象
1 class Box 2 { 3 public double width; 4 public double height; 5 public double depth; 6 7 //重載構造方法 8 public Box(Box ob) 9 {10 width = ob.width;11 height = ob.height;12 depth = ob.depth;13 }14 15 public Box(double w, double h, double d)16 {17 width = w;18 height = h;19 depth = d;20 }21 22 public Box()23 {24 width = -1;25 height = -1;26 depth = -1;27 }28 29 public Box(double len)30 {31 width = height = depth = len;32 }33 34 //計算體積35 public double volume()36 {37 return width * height * depth;38 }39 }40 41 //下面的類繼承自類Box42 class BoxWeight extends Box43 {44 double weight;45 46 //BoxWeight的構造方法47 BoxWeight (double w, double h, double d, double m)48 {49 width = w;50 height = h;51 depth = d;52 weight = m;53 }54 }55 class RefDemo 56 { 57 public static void main(String args[]) 58 { 59 BoxWeight weightbox = new BoxWeight(3, 5, 7, 8.37); 60 Box plainbox = new Box(); 61 double vol; 62 63 vol = weightbox.volume(); 64 System.out.println("Volume of weightbox is " + vol); 65 System.out.println("Weight of weightbox is " + 66 weightbox.weight); 67 System.out.println(); 68 // assign BoxWeight reference to Box reference 69 plainbox = weightbox; 70 71 vol = plainbox.volume(); // OK, volume() defined in Box 72 System.out.println("Volume of plainbox is " + vol); 73 74 /* The following statement is invalid because plainbox 75 does not define a weight member. */ 76 // System.out.println("Weight of plainbox is " + plainbox.weight); 77 } 78 }weightbox是BoxWeight對象的一個引用,plainbox是Box對象的一個引用(關于JAVA中引用的概念和C++有些不同,可以參考http://blog.sina.com.cn/s/blog_7fb1495b01012sfn.html,寫的很詳細)。既然 BoxWeight是Box的一個子類,允許用一個weightbox對象的引用給plainbox賦值,但是plainbox是不可以訪問weight的,因為超類不知道子類增加的屬性weight,所以最后一行被注釋掉,Box的引用訪問weight域是不可能的,因為它沒有定義這個域。
四、關于super
super有兩種通用形式。第一種調用超類的構造方法。第二種用來訪問被子類的成員隱藏的超類成員。
- 使用super調用超類構造函數
考慮下面BoxWeight()的改進版本:
class BoxWeight extends Box{ double weight; //BoxWeight的構造方法 BoxWeight (double w, double h, double d, double m) { super(w, h, d);// 調用超類構造方法 weight = m; }}這樣Box完全可以把成員width,height,depth聲明為private,子類在初始化這些成員時并沒有自己動手,而是調用超類的構造方法去初始化這些值(超類自己的構造方法顯然可以訪問自己private成員),這樣有利于超類的封裝。而且超類將根據super里面參數的形式決定調用哪一個構造方法,看下面程序:
1 class Box 2 { 3 //成員全部“私有化” 4 private double width; 5 private double height; 6 private double depth; 7 8 //重載構造方法 9 public Box(Box ob) 10 { 11 width = ob.width; 12 height = ob.height; 13 depth = ob.depth; 14 } 15 16 public Box(double w, double h, double d) 17 { 18 width = w; 19 height = h; 20 depth = d; 21 } 22 23 public Box() 24 { 25 width = -1; 26 height = -1; 27 depth = -1; 28 } 29 30 public Box(double len) 31 { 32 width = height = depth = len; 33 } 34 35 //計算體積 36 public double volume() 37 { 38 return width * height * depth; 39 } 40 } 41 42 //下面的類繼承自類Box 43 class BoxWeight extends Box 44 { 45 double weight; 46 47 //用super調用BoxWeight的構造方法 48 BoxWeight(BoxWeight ob) 49 { 50 super(ob); 51 weight = ob.weight; 52 } 53 54 BoxWeight (double w, double h, double d, double m) 55 { 56 super(w, h, d); 57 weight = m; 58 } 59 // default constructor 60 BoxWeight() { 61 super(); 62 weight = -1; 63 } 64 65 BoxWeight(double len, double m) { 66 super(len); 67 weight = m; 68 } 69 } 70 public class myJavaTest 71 { 72 public static void main(String args[]) { 73 BoxWeight mybox1 = new BoxWeight(10, 20, 15, 34.3); 74 BoxWeight mybox2 = new BoxWeight(2, 3, 4, 0.076); 75 BoxWeight mybox3 = new BoxWeight(); // default 76 BoxWeight mycube = new BoxWeight(3, 2); 77 BoxWeight myclone = new BoxWeight(mybox1); 78 double vol; 79 80 vol = mybox1.volume(); 81 System.out.println("Volume of mybox1 is " + vol); 82 System.out.println("Weight of mybox1 is " + mybox1.weight); 83 System.out.println(); 84 85 vol = mybox2.volume(); 86 System.out.println("Volume of mybox2 is " + vol); 87 System.out.println("Weight of mybox2 is " + mybox2.weight); 88 System.out.println(); 89 90 vol = mybox3.volume(); 91 System.out.println("Volume of mybox3 is " + vol); 92 System.out.println("Weight of mybox3 is " + mybox3.weight); 93 System.out.println(); 94 95 vol = myclone.volume(); 96 System.out.println("Volume of myclone is " + vol); 97 System.out.println("Weight of myclone is " + myclone.weight); 98 System.out.println(); 99 vol = mycube.volume(); 100 System.out.println("Volume of mycube is " + vol); 101 System.out.println("Weight of mycube is " + mycube.weight); 102 System.out.println(); 103 } 104 }運行結果:
這里特別注意這個構造方法:
BoxWeight(BoxWeight ob) { super(ob); //子類對象賦給超類對象 weight = ob.weight; }可以看出一個超類引用了子類對象,但是超類只知道它自己的成員,而weight它是不知道的,需要單獨初始化。
特別記住,super()必須是子類構造方法中第一個執行的語句。
- super的第二種用法
通用形式:super.超類的成員域, 其中“超類的成員域”可以是成員變量和成員方法。多數是用于超類成員名被子類中同樣的成員名隱藏的情況,看一個簡單的例子:
1 class A 2 { 3 int xiaoming; 4 } 5 6 class B extends A { 7 int xiaoming; // 這子類中的同名變量xiaoming會隱藏超類中的xiaoming 8 9 B(int a, int b) { 10 super.xiaoming = a; // xiaoming in A 11 xiaoming = b; // xiaoming in B 12 } 13 14 void show() 15 { 16 System.out.println("xiaomingin superclass: " + super.xiaoming); 17 System.out.println("xiaoming in subclass: " + xiaoming); 18 } 19 } 20 21 class UseSuper22 { 23 public static void main(String args[]) 24 { 25 B subOb = new B(1, 2); 26 27 subOb.show(); 28 } 29 }輸出如下:
xiaoming in superclass: 1
xiaoming in subclass: 2
這個例子只是展示了super可以訪問被子類隱藏的超類的成員變量,但是不要忘記,super同樣可以訪問被子類隱藏的超類的成員方法。
新聞熱點
疑難解答