java面向对象(二)之继承
繼承
介紹
繼承是從已有的類中派生出新的類,新的類能吸收已有類的數據屬性和行為,并能擴展新的能力。繼承即常說的is-a關系。子類繼承父類的特征和行為,使得子類具有父類的各種屬性和方法。或子類從父類繼承方法,使得子類具有父類相同的行為。
例子:
比如可以先定義一個類叫車,車有以下屬性:車體大小,顏色,方向盤,輪胎,而又由車這個類派生出轎車和卡車兩個類,為轎車添加一個小后備箱,而為卡車添加一個大貨箱。
繼承所表達的就是一種對象類之間的相交關系,它使得某類對象可以繼承另外一類對象的數據成員和成員方法。若類B繼承類A,則屬于B的對象便具有類A的全部或部分性質(數據屬性)和功能(操作),我們稱被繼承的類A為基類、父類或超類,而稱繼承類B為A的派生類或子類。
表示父類和子類的術語:父類和子類、超類和子類、基類和派生類,他們表示的是同一個意思。
為什么需要繼承
開發動物類,其中動物分別為企鵝以及老鼠,要求如下:
企鵝:屬性(姓名,id),方法(吃,睡,自我介紹)
老鼠:屬性(姓名,id),方法(吃,睡,自我介紹)
企鵝和老鼠都是動物我們是不是可以寫一個動物類,這樣代碼是不是簡潔了許多。有的人說我就想單獨建兩個類寫這個屬性,我只能告訴你可以,但這好比,你父親給你了幾百萬,你偏不要,把這些錢扔了非要自己去掙,你想這樣我也沒辦法。既然java給我們提供了繼承我們就要好好用這樣會大大提高我們的開發效率,比如:維護性提高了,代碼也更加簡潔,提高代碼的復用性也提高了(復用性指可以多次使用,不用再多次寫同樣的代碼)。
作用:
1、繼承可以減少重復的代碼。比如父類已經提供的方法,子類可以直接使用,不必再去實現。
2、繼承是多態性的前提。當然使用繼承的同時也提高了類的耦合度。
當你不需要父類的屬性時,可以覆蓋調原屬性。
Java繼承分類
繼承分為單繼承和多重繼承。單繼承是指一個子類最多只能有一個父類。多繼承是一個子類可以有二個以上的父類。由于多繼承會帶來二義性,在實際應用中應盡量使用單繼承。J**ava語言中的類只支持單繼承,而接口支持多繼承。Java中多繼承的功能是通過接口(interface)來間接實現的**。
繼承實現
繼承可以使用 extends 和 implements 這兩個關鍵字來實現繼承,而且所有的類都是繼承于 java.lang.Object,當一個類沒有繼承的兩個關鍵字,則默認繼承object(這個類在 java.lang 包中,所以不需要 import)祖先類。
繼承的初始化順序:
父類—>父類的初始化對象中的屬性—>父類的構造方法—>子類—>子類的初始化對象中的屬性—>子類的構造方法
若有構造方法:則先執行屬性,再執行構造方法
若構造方法中沒有對name屬性進行賦值,則name的值為類屬性所賦的值
extends關鍵字
在 Java 中,類的繼承是單一繼承,也就是說,一個子類只能擁有一個父類,所以 extends 只能繼承一個類。
/*動物類*/ public class Animal { private String name; private int id; public Animal(String myName, String myid) { //初始化屬性值} public void eat() { //吃東西方法的具體實現 } public void sleep() { //睡覺方法的具體實現 } } /*企鵝是動物,所以可以繼承動物類*/ public class Penguin extends Animal{ //企鵝繼承了動物類,所以擁有了動物類的屬性和方法 }implements關鍵字
使用 implements 關鍵字可以變相的使java具有多繼承的特性,使用范圍為類繼承接口的情況,可以同時繼承多個接口(接口跟接口之間采用逗號分隔)。
public interface A {public void eat();public void sleep(); }public interface B {public void show(); }public class C implements A,B { }super 與 this 關鍵字
super關鍵字:我們可以通過super關鍵字來實現對父類成員的訪問,用來引用當前對象的父類。
注:
1.只能在構造方法或實例方法內使用super關鍵字,而在靜態方法和靜態代碼塊內不能使用super關鍵字
2.如果父類中的成員變量和方法被定義為private類型,那么子類永遠無法訪問它們,如果試圖采用super.var的形式去訪問父類的private類型的var變量,就會導致編譯錯誤
this關鍵字:指向自己的引用,表示當前正在調用此方法的對象引用。
注:
1.當具多個重載的構造器時,且一個構造器需要調用另外一個構造其,在其第一行使用this(param)形式調用,且只能在第一行;
2.當對象中一個方法需要調用本對象中其他方法時,使用this作為主調,也可以不寫,實際上默認就是this作為主調;
3.當對象屬性和方法中的局部變量名稱相同時,在該方法中需要顯式的使用this作為主調,以表示對象的屬性,若不存在此問題,可以不顯式的寫this。
其實,其牽涉到的一個問題就是變量的查找規則:先局部變量 => 當前類中定義的變量 => 其父類中定義的可以被子類繼承的變量 => 父類…
這塊要完全理解需要看上面我寫的“繼承的初始化順序”從這里可以看到程序是如何初始化的。
/*** 父類* @author gacl**/ class FatherClass {public int value;public void f() {value=100;System.out.println("父類的value屬性值="+value);} }/*** 子類ChildClass從父類FatherClass繼承*/ class ChildClass extends FatherClass {/*** 子類除了繼承父類所具有的valu屬性外,自己又另外聲明了一個value屬性,* 也就是說,此時的子類擁有兩個value屬性。*/public int value;/*** 在子類ChildClass里面重寫了從父類繼承下來的f()方法里面的實現,即重寫了f()方法的方法體。*/public void f() {super.f();//使用super作為父類對象的引用對象來調用父類對象里面的f()方法value=200;//這個value是子類自己定義的那個valu,不是從父類繼承下來的那個valueSystem.out.println("子類的value屬性值="+value);System.out.println(value);//打印出來的是子類自定義的那個value的值,這個值是200/*** 打印出來的是父類里面的value值,由于子類在重寫從父類繼承下來的f()方法時,* 第一句話“super.f();”是讓父類對象的引用對象調用父類對象的f()方法,* 即相當于是這個父類對象自己調用f()方法去改變自己的value屬性的值,由0變了100。* 所以這里打印出來的value值是100。*/System.out.println(super.value);} }/*** 測試類*/ public class TestInherit {public static void main(String[] args) {ChildClass cc = new ChildClass();cc.f();} }運行結果:
父類的value屬性值=100
子類的value屬性值=200
200
100
分析:
執行 ChlidClass cc = new ChlidClass();
首先在棧空間里面會產生一個變量cc,cc里面的值是什么這不好說,總而言之,通過這個值我們可以找到new出來的ChlidClass對象。由于子類ChlidClass是從父類FatherClass繼承下來的,所以當我們new一個子類對象的時候,這個子類對象里面會包含有一個父類對象,而這個父類對象擁有他自身的屬性value。這個value成員變量在FatherClass類里面聲明的時候并沒有對他進行初始化,所以系統默認給它初始化為0,成員變量(在類里面聲明)在聲明時可以不給它初始化,編譯器會自動給這個成員變量初始化,但局部變量(在方法里面聲明)在聲明時一定要給它初始化,因為編譯器不會自動給局部變量初始化,任何變量在使用之前必須對它進行初始化。
子類在繼承父類value屬性的同時,自己也單獨定義了一個value屬性,所以當我們new出一個子類對象的時候,這個對象會有兩個value屬性,一個是從父類繼承下來的value,另一個是自己的value。在子類里定義的成員變量value在聲明時也沒有給它初始化,所以編譯器默認給它初始化為0。即(父類的value為0,子類的value為0;)
執行第二句話: cc.f();
當new一個對象出來的時候,這個對象會產生一個this的引用,這個this引用指向對象自身。如果new出來的對象是一個子類對象的話,那么這個子類對象里面還會有一個super引用,這個super指向當前對象里面的父對象。所以相當于程序里面有一個this,this指向對象自己,還有一個super,super指向當前對象里面的父對象。
這里調用重寫之后的f()方法,方法體內的第一句話:“super.f();”是讓這個子類對象里面的父對象自己調用自己的f()方法去改變自己value屬性的值,父對象通過指向他的引用super來調用自己的f()方法,所以執行完這一句以后,父對象里面的value的值變成了100。接著執行“value=200;”這里的vaule是子類對象自己聲明的value,不是從父類繼承下來的那個value。所以這句話執行完畢后,子類對象自己本身的value值變成了200。
總結
以上是生活随笔為你收集整理的java面向对象(二)之继承的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux运维并行批量操作命令pssh的
- 下一篇: 官司在即,品胜董事长对话苹果副总裁,打脸