標籤:amp family lang 資料 log 類的方法 xtend 可見度 center
Java三大特性之繼承
一、介紹
筆記重點:構造器、protected關鍵字(這個自行查閱)、向上轉型、private關鍵字(繼承非常重要的要點)
複用代碼是Java眾多令人信服的功能之一。但要想成為極具革命性的語言,僅僅能夠複製代碼並對加以改變是不夠的,它還必須能夠做更多的事情。在這句話中最令人信服的是“複用代碼”,儘可能的複用代碼使我們程式員一直在追求的。
繼承是使用已存在的類的定義作為基礎建立新類的技術,新類的定義可以增加新的資料或新的功能,也可以用父類的功能,但不能選擇性地繼承父類。通過使用繼承我們能夠非常方便地複用以前的代碼,能夠大大的提高開發的效率。
為什麼要繼承?
答:通過繼承可以使對對象的描述更加清晰,可以實現代碼的複用,可以實現重寫類中的變數或方法。
二、深入理解繼承
1.Java的繼承具有單繼承的特點,即只能繼承一個父類,每個子類只有一個直接父類,但是其父類又可以繼承於另一個類,從而實現了子類可以間接繼承多個父類,但其本質上劃分仍然是一個父類和子類的關係。
2.Java的繼承通過extends關鍵字來實現,實現繼承的類被稱為子類,被繼承的類稱為父類(有的也稱其為基類、超類)
3.子類擁有父類非private的屬性和方法。(便於理解是這麼和你們說的,這種說法其實是錯的 =.=!暫且這麼理解好了。)
4.子類可以擁有自己屬性和方法,即子類可以對父類進行擴充。
5.子類可以用自己的方式實現父類的方法。
6.為什麼國內把extends翻譯成繼承呢?除了與曆史原因有關外,把extends翻譯成為繼承也是有其道理的:子類擴充父類,將可以獲得父類的全部屬性和方法,這與漢語中得繼承(子輩從父輩那裡獲得一筆財富成為繼承)具有很好的類似性。
三、什麼樣的類不能被繼承呢?
1.final(終態)修飾的類是無法被繼承的,但是也不要誤解有final的類都不能被繼承。
Example 1:
Example 2:
2.構造器(注意下面有構造器的相關介紹)被private關鍵字修飾的類無法被繼承。必須定義顯式建構函式才能被繼承(例如被protected與private關鍵字修飾)。
Example 1:
四、構造器(簡單介紹上邊有個例子)
什麼是構造器?
答:簡單來說構造器即是與類名相同的特殊方法,但它沒有傳回值。深入來說Java中引入構造器,確保每一個對象都得到初始化,Java在有能力操作對象之前,系統會自動調用相應的構造器,保證初始化的進行。構造器最大的用處就是在建立對象時執行初始化,當建立一個對象時,系統會為這個對象的執行個體進行預設的初始化。如果想改變這種預設的初始化,就可以通過自訂構造器來實現。在java中,使用new關鍵是調用構造器,從而返回該類的執行個體。也就是說:構造方法是定義在Java類中的一個用來初始化對象的方法,是建立對象的根本途徑 。
使用構造器要注意一下幾點:1.如果我們沒有自己定義構造方法,系統就會預設為該類提供一個無參的構造器。一旦我們為一個類提供了構造器,系統將不會該類提 預設無參的構造器。(下面提供例子 Example 1、2 供理解)
2.有參的構造方法和無參構造方法是可以同時存在的(方法重載)//不提供例子,自己敲。
3.構造方法不但可以給屬性賦值,還可以保證給對象的屬性賦一個合理的值。
Example 1:
1 public class test1 { 2 public static void main(String[] args) { 3 // TODO 自動產生的方法存根 4 test2 p=new test2(); 5 System.out.println("Hello"); 6 } 7 } 8 class test2{ 9 private String b;10 //public test2(){}---系統已經預設為該類提供無參的構造方法11 }
Example 2:
1 public class test1 { 2 public static void main(String[] args) { 3 // TODO 自動產生的方法存根 4 //new關鍵是調用構造器,返回該類執行個體 5 test2 p=new test2();//報錯 6 System.out.println("Hello"); 7 } 8 } 9 class test2{10 private String b;11 //因為我們已經定義了有參構造方法,所以系統將不再提供預設的無參構造方法12 public test2(String b){13 this.b=b;14 }15 }
補個重點:在構造器中調用父類構造器來完成初始化,而父類構造器具有執行父類初始化所需要的所有知識和能力。
1 public class test1 { 2 public static void main(String[] args) { 3 // TODO 自動產生的方法存根 4 //new關鍵是調用構造器,返回該類執行個體 5 test3 p=new test3();//報錯 6 System.out.println("Hello"); 7 } 8 } 9 class test2{10 public test2(){11 System.out.println("test2");12 }13 }14 class test3 extends test2{15 public test3(){16 //super();---已經預設調用父類構造器17 System.out.println("test3");18 }19 }
輸出:
test2 test3 Hello
解析:子類繼承父類是從父類向外擴充的,從父類向子類一層層擴充。子類會預設調用父類的構造器,這個調用是有前提的父類必須要有預設的構造器,如果沒有就會報錯,編譯器會報錯:無法找到符合父類形式的構造器。
1 public class test1 { 2 public static void main(String[] args) { 3 // TODO 自動產生的方法存根 4 //new關鍵是調用構造器,返回該類執行個體 5 test3 p=new test3();//報錯 6 System.out.println("Hello"); 7 } 8 } 9 class test2{10 public test2(String name){11 System.out.println("test2------"+name);12 }13 }14 class test3 extends test2{15 public test3(){16 super("zs");//---必須調用父類有參構造器17 System.out.println("test3");18 }19 }
輸出:
test2------zs test3 Hello
總結:繼承時子類會預設調用父類的構造器,但是如果沒有預設的父類構造器,子類必須要顯示的指定父類的構造器,而且必須是在子類構造器中做的第一件事(第一行代碼)。
五、向上轉型
繼承中父類與子類是“is a”的關係,比如“學生”類繼承了“人”這個類,那麼可以說學生是一個人(這就是向上轉型)。向上轉型是安全的,但是可能會丟失一部分屬性和方法(轉型過程中,子類的新有的方法都會遺失掉,在編譯時間,系統會提供找不到方法的錯誤)。
1 public class test1 { 2 public static void main(String[] args) { 3 // TODO 自動產生的方法存根 4 //new關鍵是調用構造器,返回該類執行個體 5 test3 p=new test3();//報錯 6 test2 p1=new test2("351"); 7 p1.p(p);//-----轉型並且是安全的 8 } 9 }10 class test2{11 public test2(String name){12 System.out.println("test2------"+name);13 }14 public void p(test2 p1){15 System.out.println("+++++");16 }17 }18 class test3 extends test2{19 public test3(){20 super("zs");21 System.out.println("test3");22 }23 }
擴充:
1、父類變,子類就必須變。
2、繼承破壞了封裝,對於父類而言,它的實現細節對與子類來說都是透明的。
3、其實子類不僅擁有父類的非private的屬性和方法,也擁有父類的private的屬性和方法。首先需要明確:private、public和protected這幾個關鍵字,和繼承沒有關係,有關係的應該叫做“可見度”。父類不能控制自己的成員被子類繼承走,但是可以約束某些被繼承的成員變數,對於子類來說是不可見的。
(個人理解為子類擁有父類的所有屬性和方法只是無法使用,這個不是瞎扯是可以查出來的)。
java隨筆:三大特性之繼承