您好,登錄后才能下訂單哦!
這篇文章主要介紹“Java繼承與多態的概念是什么及怎么實現”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“Java繼承與多態的概念是什么及怎么實現”文章能幫助大家解決問題。
繼承機制:是面向對象程序設計是代碼可以復用的最重要手段,允許程序員在保持原有類特性的基礎上進行擴展,增加新的功能,產生的新類,成為派生類/子類。繼承主要解決的問題是:共性的抽取,實現代碼的復用。
表示類與類的繼承關系,需要借助關鍵字extends,語法如下:
修飾符 class 子類/派生類 extends 父類/基類/超類{
//…………
}
子類會將父類的成員變量或者成員方法繼承到子類中
子類繼承父類后,必須添加自己特有的成員,體現與基類的不同
不存在同名成員變量時,正常訪問就行
存在同名成員變量,使用(super.變量名)實現父類成員變量的訪問
public class Base { int a; int b; int c; } public class Derived extends Base{ int a; // 與父類中成員a同名,且類型相同 char b; // 與父類中成員b同名,但類型不同 public void method(){ a = 100; // 訪問父類繼承的a,還是子類自己新增的a? b = 101; // 訪問父類繼承的b,還是子類自己新增的b? c = 102; // 子類沒有c,訪問的肯定是從父類繼承下來的c } }
訪問成員變量時,優先訪問自己的成員變量。即同名成員變量訪問時,優先訪問子類的。即:子類將父類的成員隱藏了
成員變量訪問遵循就近原則,自己有優先自己的,自己沒有則向父類中查找。
成員方法名字不同,正常訪問即可
成員方法名字相同,可以通過 【super.方法名】訪問同名父類方法
如果父類和子類同名方法的參數列表不同(重載),根據調用方法時傳遞的參數選擇合適的方法訪問。
如果父類和子類的同名方法原型一致,則訪問子類的
super關鍵字的主要作用是:在子類方法中訪問父類的同名成員。(只能在非靜態方法中使用)
public class Base { int a; int b; public void methodA(){ System.out.println("Base中的methodA()"); } public void methodB(){ System.out.println("Base中的methodB()"); } public class Derived extends Base{ int a; char b; // 與父類中methodA()構成重載 public void methodA(int a) { System.out.println("Derived中的method()方法"); } // 與父類中methodB()構成重寫 public void methodB(){ System.out.println("Derived中的methodB()方法"); } public void methodC(){ a = 100; // 等價于: this.a = 100; b = 101; // 等價于: this.b = 101; // 訪問父類的成員變量時,需要借助super關鍵字 // super是獲取到子類對象中從基類繼承下來的部分 super.a = 200; super.b = 201; methodA(); // 沒有傳參,訪問父類中的methodA() methodA(20); // 傳遞int參數,訪問子類中的methodA(int) methodB(); // 直接訪問,則永遠訪問到的都是子類中的methodA(),基類的無法訪問到 super.methodB(); // 訪問基類的methodB() } }
子類對象構造時,需要先調用父類的構造方法,然后執行子類的構造方法。
public class Base { public Base(){ System.out.println("Base()"); } } public class Derived extends Base{ public Derived(){ // super(); // 注意子類構造方法中默認會調用基類的無參構造方法:super(), // 用戶沒有寫時,編譯器會自動添加,而且super()必須是子類構造方法中第一條語句, // 并且只能出現一次 System.out.println("Derived()"); } }
若父類顯示定義無參或者默認的構造函數,在子類的構造方法第一行默認有隱含的super()調用。
父類定義帶參數的構造方法時,編譯器不會再給子類生成默認的構造方法,需要子類顯式定義,并在子類構造方法中調用合適的父類構造方法
子類構造方法中,super(……)調用父類構造方法,必須是子類構造方法的第一條語句
super(……)只能在子類構造方法中出現一次,并且不能和this同時出現
super和this都可以在成員方法中用來訪問成員變量和調用其他的成員函數,都可以作為構造方法的第一條語句,那么它們之間的區別是什么?
(1)相同點
都是java的關鍵字
只能在類的非靜態方法中使用,用來訪問非靜態成員方法和屬性
必須作為構造方法中的第一條語句,并且不能同時存在
(2)不同點
this是當前對象的引用,super是子類對象中從父類繼承的成員的引用
this是非靜態成員方法的一個隱藏參數,super不是隱藏參數
在構造方法中:this()用于調用本類的構造方法,super()用來調用父類構造方法,兩種調用不能同時出現在構造方法中
子類的構造方法中一定會存在super()的調用,但是this()用戶不寫就沒有
【普通類】
靜態代碼塊先執行,并且只執行一次,在類加載階段執行
當有對象創建時,才會執行實例代碼塊,最后執行構造方法
【繼承關系上的執行順序】
父類靜態代碼塊優先于子類靜態代碼塊執行,最早執行
父類實例代碼塊和父類構造方法緊接著執行
子類的實例代碼塊和構造方法最后執行
第二次實例化子類對象時,父類和子類的靜態代碼塊不會再執行
【注】Java中不支持多繼承
super只能指代直接父類
繼承關系一般不超過三層
修飾變量時,表示常量(不能修改)
修飾類:此類不能被繼承
修飾方法:表示方法不能被重寫
組合和繼承都能實現代碼的復用。組合沒有涉及到特殊的語法(如extend關鍵字),僅僅是將一個類的實例作為另一個類的屬性。
繼承表示對象與對象之間是is-a的關系
組合表示對象與對象之間是has-a的關系
一般建議:能用組合盡量用組合
通過父類類型的引用調用子類對象,向上轉型是安全的
【發生向上轉型的時機】
直接賦值
方法傳參
函數的返回值
public class TestAnimal { // 2. 函數傳參:形參為父類引用,可以接收任意子類的對象 public static void eatFood(Animal a) { a.eat(); } // 3. 作返回值:返回任意子類對象 public static Animal buyAnimal(String var) { if ("狗" == var) { return new Dog("狗狗", 1); } else if ("貓" == var) { return new Cat("貓貓", 1); } else { return null; } } public static void main(String[] args) { Animal cat = new Cat("元寶", 2); // 1. 直接賦值:子類對象賦值給父類對象 Dog dog = new Dog("小七", 1); } }
優缺點:
優點:讓代碼更加靈活
缺點:不能訪問到子類特有的方法
函數名相同、參數列表相同、返回值相同或是【協變類型】(父子類關系)
【方法重寫的規則】
重寫的方法訪問權限不能比父類中原方法的的權限低;
父類中被static、private、final修飾的方法、構造方法不能被重寫;
重寫的方法,可以使用 @override 注解來顯示指定(幫助我們進行一些合法性的檢驗)。比如方法名拼寫錯誤,編譯會報錯;
重寫的返回值類型可以不同,但是必須具有父子關系。
被final修飾的方法,叫做密封方法,該方法不能被重寫。
外部類只能是public或者默認權限
【動態綁定和靜態綁定】
動態綁定:發生的條件(1、父類引用引用子類對象;2、通過父類引用,可以訪問到子類中的方法)。后期綁定,即在編譯時不能確定方法的行為,需要等到程序運行時,才能夠確定調用哪個類的方法;
靜態綁定:前期綁定,編譯時,根據用戶傳遞的參數類型確定具體的調用方法(函數重載)
一個引用調用同一個方法,可以表現出不同的形式,這種思想稱為多態。在父類的構造方法中不要調用重寫的方法。
【多態實現的條件】
必須在繼承條件下
子類對父類方法進行重寫
通過父類引用調用重寫的方法
發生了向上轉型
public class Animal(){ String name; int age; public Animal(String name, int age){ this.name = name; this.age = age; } public void eat(){ System.out.println(name + "吃飯"); } } public class Cat extends Animal{ public Cat(String name, int age){ super(name, age); } @Override public void eat(){ System.out.println(name+"吃魚~~~"); } } public class Dog extends Animal { public Dog(String name, int age){ super(name, age); } @Override public void eat(){ System.out.println(name+"吃骨頭~~~"); } } public class TestAnimal { // 編譯器在編譯代碼時,并不知道要調用Dog 還是 Cat 中eat的方法 // 等程序運行起來后,形參a引用的具體對象確定后,才知道調用那個方法 // 注意:此處的形參類型必須時父類類型才可以 public static void eat(Animal a){ a.eat(); } public static void main(String[] args) { Animal animal1 = new Cat("元寶",2); Animal animal2 = new Dog("小七", 1); eat(animal1); eat(animal2); } }
【注】Java中所有的類默認繼承Object類
關于“Java繼承與多態的概念是什么及怎么實現”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。