Java 從入門到進階之路(十)
之前的文章我們介紹了一下 Java 中的引用型陣列型別,接下來我們再來看一下 Java 中的繼承。
繼承的概念
繼承是java面向物件程式設計技術的一塊基石,因為它允許建立分等級層次的類。
繼承就是子類繼承父類的特徵和行為,使得子類物件(例項)具有父類的例項域和方法,或子類從父類繼承方法,使得子類具有父類相同的行為。
在日常生活中,我們會養些貓和狗,從程式的角度講貓和狗都屬於物件,那麼我們就可以根據其特性來定義,如下:
1 class Dog extends Animal { 2 String name; 3 String color; 4 int age; 5 6 void run() { 7 System.out.println("我可以跑"); 8 } 9 10 void lookDoor() { 11 System.out.println("我可以看門"); 12 } 13 } 14 15 class Cat { 16 String name; 17 String color; 18 int age; 19 20 void run() { 21 System.out.println("我可以跑"); 22 } 23 24 void catchMouse() { 25 System.out.println("我可以抓老鼠"); 26 } 27 }
我們在定義 Dog 和 Cat 類的時候發現它們絕大部分屬性和方法是相同的。那這樣的話我們再定義其他動物的時候同樣會出現這種氣礦,這就造成了大量程式碼的重複,造成程式臃腫,不易維護。
我們可以這樣解決上面的問題,將 Dog 和 Cat 類裡相同的屬性和方法寫到一個父類裡,自己特有的方法在自己的類裡完成,這樣就可以有效的解決上面的問題,其實這就是 Java 類的繼承,如下:
1 public class HelloWorld { 2 public static void main(String[] args) { 3 Dog dog = new Dog(); 4 dog.run(); // 我可以跑 5 dog.lookDoor(); // 我可以看門 6 7 Cat cat = new Cat(); 8 cat.run(); // 我可以跑 9 cat.catchMouse(); // 我可以抓老鼠 10 } 11 } 12 13 class Animal{ 14 String name; 15 String color; 16 int age; 17 18 void run() { 19 System.out.println("我可以跑"); 20 } 21 } 22 23 class Dog extends Animal { 24 void lookDoor() { 25 System.out.println("我可以看門"); 26 } 27 } 28 29 class Cat extends Animal { 30 void catchMouse() { 31 System.out.println("我可以抓老鼠"); 32 } 33 }
在上面的程式碼中,我們定義類一個 Animal 類,裡面定義了 Dog 和 Cat 類中相同的屬性和方法,然後我們在定義 Dog 和 Cat 類的時候通過 extends Animal 的方式來繼承 Animal 類,當我們繼承 Animal 類的時候,Animal 類中的屬性和方法就會被一併繼承過來,這樣我們在宣告 Dog 和 Cat 類的時候便可以呼叫從 Animal 類及成果來的屬性和方法,這就是繼承。
繼承:
1、目的:避免程式碼重複,有利於程式碼的重用
2、通過 extends 實現繼承
3、父類:所有子類所用共有的屬性和方法;子類:子類所特有的屬性和方法
4、子類繼承父類後,子類具有 子類+父類 的屬性和方法
5、一個父類可以有多個子類,一個子類只能有一個父類-----單一繼承
6、繼承具有傳遞性
7、Java 規定:構造子類之前必須先構造父類,子類構造中若沒有呼叫父類的構造,則預設super(),若自己調了,則不再預設提供。
在上面的5,6條我們可以看出,在寫程式時,我們不能這樣 class Dog extends Cat extends Animal 的形式來實現繼承,這樣會出現編譯錯誤,但是我們可以通過 class Cat extends Animal class Dog extends Cat 的形式來逐層進行繼承。
在上面的程式碼中我們已經瞭解了 Java 的繼承,接下來我們在結合之前說到的構造方法來介紹一下 super
1 public class HelloWorld { 2 public static void main(String[] args) { 3 Dog dog = new Dog(); 4 dog.run(); // 我可以跑 5 dog.lookDoor(); // 我可以看門 6 dog.name = "旺財"; 7 dog.color = "黃色"; 8 dog.age = 8; 9 System.out.println("我叫" + dog.name + ",今年" + dog.age + ",是" + dog.color + "的"); // 我叫旺財,今年8,是黃色的 10 11 Cat cat = new Cat("咪咪", "白色", 5); 12 cat.run(); // 我可以跑 13 cat.catchMouse(); // 我可以抓老鼠 14 System.out.println("我叫" + cat.name + ",今年" + cat.age + ",是" + cat.color + "的"); // 我叫咪咪,今年5,是白色的 15 } 16 } 17 18 class Animal { 19 String name; 20 String color; 21 int age; 22 23 Animal() { 24 25 } 26 27 Animal(String name, String color, int age) { 28 this.name = name; 29 this.color = color; 30 this.age = age; 31 } 32 33 void run() { 34 System.out.println("我可以跑"); 35 } 36 } 37 38 class Dog extends Animal { 39 Dog() { 40 super(); 41 } 42 43 void lookDoor() { 44 System.out.println("我可以看門"); 45 } 46 } 47 48 class Cat extends Animal { 49 Cat(String name, String color, int age) { 50 super(name, color, age); 51 } 52 53 void catchMouse() { 54 System.out.println("我可以抓老鼠"); 55 } 56 }
在上面的程式碼中,我們在父類 Animal 類中分別定義了一個無參構造和一個有參構造,在子類 Dog 中定義了一個無參構造,在子類 Cat 中定義類一個有參構造,我們發現,在子類的構造方法中我們添加了一個 super() 的方法,通過這種方法我們就可以繼承來自父類的構造方法,從而在例項化我們的子類的時候初始化我們想要的引數,在繼承父類的有參構造的時候需要將父類有參構造的引數傳遞進來。
接下來我們來看下面的程式碼:
1 public class HelloWorld { 2 public static void main(String[] args) { 3 Dog dog1 = new Dog(); 4 Dog dog2 = new Animal(); // 編譯錯誤 5 Animal animal1 = new Animal(); 6 animal1.run(); // 我可以跑 7 animal1.lookDoor(); // 編譯錯誤 8 Animal animal2 = new Dog(); 9 animal2.run(); // 我可以跑 10 animal1.lookDoor(); // 編譯錯誤 11 } 12 } 13 14 class Animal { 15 String name; 16 String color; 17 int age; 18 19 Animal() { 20 21 } 22 23 Animal(String name, String color, int age) { 24 this.name = name; 25 this.color = color; 26 this.age = age; 27 } 28 29 void run() { 30 System.out.println("我可以跑"); 31 } 32 } 33 34 class Dog extends Animal { 35 Dog() { 36 super(); 37 } 38 39 void lookDoor() { 40 System.out.println("我可以看門"); 41 } 42 }
在上面的程式碼中,我們如果通過 new Dog() 來建立一個 Dog 物件是完全沒有問題的,通過 new Animal() 來建立一個 Animal 物件也是沒有問題的,但是通過 new Animal() 來建立一個 Dog 物件會編譯錯誤,通過 new Dog() 來建立一個 Animal 物件也是沒有問題的,我們可以這樣理解,new 類名() 所指向的類必須是本類或父類,不能是子類,即等號左側的型別必須大於或等於等號右側的 new 出來的類。當大於時我們稱之為向上造型。向上造型後 子類 將不再具備其自己定義的方法,只有父類的方法。
&n