Java基礎-四要素之一《繼承》

來源:互聯網
上載者:User

標籤:

 

 繼承的概念:

   繼承在本職上是特殊——一般的關係,即常說的is-a關係。子類繼承父類,表明子類是一種特殊的父類,並且具有父類所不具有的一些屬性或方法。

   繼承是所有OOP語言不可缺少的部分,在java中使用extends關鍵字來表示繼承關係。當建立一個類時,總是在繼承,如果沒有明確指出要繼承的類,就總是隱式地從根類Object進行繼承。比如下面這段代碼:

class Person {    public Person() {             }} class Man extends Person {    public Man() {             }}

 

  類Man繼承於Person類,這樣一來的話,Person類稱為父類(基類),Man類稱為子類(匯出類)。如果兩個類存在繼承關係,則子類會自動繼承父類的方法和變數,在子類中可以調用父類的方法和變數。在java中,只允許單繼承,也就是說 一個類最多隻能顯示地繼承於一個父類。但是一個類卻可以被多個類繼承,也就是說一個類可以擁有多個子類。

 

1.子類繼承父類的成員變數

當子類繼承了某個類之後,便可以使用父類中的成員變數,但是並不是完全繼承父類的所有成員變數。具體的原則如下:

  1)能夠繼承父類的public和protected成員變數;不能夠繼承父類的private成員變數;  2)對於父類的包存取權限成員變數,如果子類和父類在同一個包下,則子類能夠繼承;否則,子類不能夠繼承;  3)對於子類可以繼承的父類成員變數,如果在子類中出現了同名稱的成員變數,則會發生隱藏現象,即子類的成員變數會屏蔽掉父類的同名成員變數。如果要在子類中訪問父類中同名成員變數,需要使用super關鍵字來進行引用。

 

2.子類繼承父類的方法

同樣地,子類也並不是完全繼承父類的所有方法。  

  1)能夠繼承父類的public和protected成員方法;不能夠繼承父類的private成員方法;  2)對於父類的包存取權限成員方法,如果子類和父類在同一個包下,則子類能夠繼承;否則,子類不能夠繼承;  3)對於子類可以繼承的父類成員方法,如果在子類中出現了同名稱的成員方法,則稱為覆蓋,即子類的成員方法會覆蓋掉父類的同名成員方法。如果要在子類中訪問父類中同名成員方法,需要使用super關鍵字來進行引用。

 

  注意:隱藏和覆蓋是不同的。隱藏是針對成員變數和靜態方法的,而覆蓋是針對普通方法的。(後面會講到)

 

3.構造器

  子類是不能夠繼承父類的構造器,但是要注意的是,如果父類的構造器都是帶有參數的,則必須在子類的構造器中顯示地通過super關鍵字調用父類的構造器並配以適當的參數列表。如果父類有無參構造器,則在子類的構造器中用super關鍵字調用父類構造器不是必須的,如果沒有使用super關鍵字,系統會自動調用父類的無參構造器。看下面這個例子就清楚了:

class Shape {         protected String name;         public Shape(){        name = "shape";    }         public Shape(String name) {        this.name = name;    }} class Circle extends Shape {         private double radius;         public Circle() {        radius = 0;    }         public Circle(double radius) {        this.radius = radius;    }         public Circle(double radius,String name) {        this.radius = radius;        this.name = name;    }}

這樣的代碼是沒有問題的,如果把父類的無參構造器去掉,則下面的代碼必然會出錯:

改成下面這樣也行:

 

4.super

super主要有兩種用法:

  1)super.成員變數/super.成員方法;  2)super(parameter1,parameter2....)

第一種用法主要用來在子類中調用父類的同名成員變數或者方法;

第二種主要用在子類的構造器中顯示地調用父類的構造器,要注意的是,如果是用在子類構造器中,則必須是子類構造器的第一個語句。

 

 

 

 

 

 

 

 繼承中的初始化順序:

   從類的結構上而言,其內部可以有如下四種常見形態:屬性(包括類屬性和執行個體屬性)、方法(包括類方法和執行個體方法)、構造器和初始化塊(包括類的初始化塊和執行個體的初始化塊)。對於繼承中的初始化順序,又具體分為類的初始化和對象的初始化。

 

 類初始化:

    在jvm裝載類的準備階段,首先為類的所有類屬性和類初始化塊分配記憶體空間。並在類首次初始化階段中為其進行初始化,類屬性和類初始化塊之間的定義時的順序決定了其初始化的順序。若類存在父類,則首先初始化父類的類屬性和類初始化塊,一直上溯到Object類最先執行。

 

 

 

 

 對象初始化:

    在new建立對象時,首先對對象屬性和初始化塊分配記憶體,並執行預設初始化。如果存在父類,則先為父類對象屬和初始化塊先分配記憶體並執行初始化。    然後執行父類構造器中的初始化程式,接著才開始對子類的對象屬性和初始化塊執行初始化。

 

 

 註:

1. 在對象初始化階段,屬性和方法均針對子類可以從父類繼承過來的屬性和方法而言,一般而言,都是針對父類中非private而言的。因為private修飾的為父類所特有的,子類沒有繼承過來,當new子類時,無須為其分配空間並執行初始化。當然了,父類的構造器子類也是不繼承過來的,但構造器另當別論。2. 類的初始化只執行一次,當對同一個類new多個對象時,類屬性和類初始化塊只初始化一次。

 

 繼承的好處

1,提高了代碼的複用性。2,讓類與類之間產生了關係,給第三個特徵多態提供了前提。  java中支援單繼承,一個子類只能有一個直接父類。  java支援多層繼承,當要使用一個繼承體系時,1,查看該體系中的頂層類,交接該體系的準系統。2,建立體系中的最子類對象,完成功能的使用。 

 

 

什麼時候定義繼承?

當類與類之間存在著所屬關係的時候就定義繼承。xxx是yyy中的一種,xxx extends yyy
所屬關係:is a
當本類的成員和局部變數同名用this區分。
當子父類中成員變數同名時用super區分父類。
this代表本類對象的引用
super代表父類的一個空間
重寫:當子父類中出現相同方法時,會先運行子類中的方法。
重寫的特點:方法名一樣,存取修飾詞許可權不小於父類,傳回型別一致,參數列表一致。
什麼時候用重寫?
當對一個類進行子類的擴充時,子類需要保留父類的功能聲明,
但是要定義子類中該功能的特有內容時,就使用重寫操作完成。
子父類中的構造方法的特點:
在子類構造對象時,發現,訪問子類建構函式時,父類也運行了。
原因:在子類構造方法中的第一行有一個預設的隱士語句。super();
調用父類中的空參數建構函式。
子類的執行個體化過程:子類中的構造方法都會訪問父類中的無參構造方法

 

繼承中的隱藏:

隱藏含義:實際上存在,但是對外不可見。

Java類具有三種存取控制符:private、protected和public,同時當不寫這三個存取控制符時,表現為一種預設的存取控制狀態。因此,一共具有四種存取控制層級。

具體存取控制表現如下:

private修飾的屬性或方法為該類所特有,在任何其他類中都不能直接存取;default修飾的屬性或方法具有包訪問特性,同一個包中的其他類可以訪問;protected修飾的屬性或方法在同一個中的其他類可以訪問,同時對於不在同一個包中的子類中也可以訪問;public修飾的屬性或方法外部類中都可以直接存取。

 

 

 

 

 

 

當子類繼承父類,子類可以繼承父類中具有存取控制許可權的屬性和方法(一般來說是非private修飾的),對於private修飾的父類所特有的屬性和方法,子類是不繼承過來的。

當子類需要改變繼承過來的方法時,也就是常說的重寫父類的方法。一旦重寫後,父類的此方法對子類來說表現為隱藏。以後子類的對象調用此方法時,都是調用子類重寫後

的方法,但子類對象中想調用父類原來的此方法時,可以通過如下兩種方式:

1.將子類物件類型強制轉化為父類類型,進行調用;

2.通過super調用。

同樣的,如果在子類中定義父類中相同名稱的屬性時,父類屬性在子類中表現為隱藏。

 

 

繼承中的this和super:

構造器中的this表示當前正在初始化的對象引用,方法中的this表示當前正在調用此方法的對象引用。this具體用法表現在一下幾個方面:

1.當具多個重載的構造器時,且一個構造器需要調用另外一個構造其,在其第一行使用this(param)形式調用,且只能在第一行;

2.當對象中一個方法需要調用本對象中其他方法時,使用this作為主調,也可以不寫,實際上預設就是this作為主調;

3.當對象屬性和方法中的局部變數名稱相同時,在該方法中需要顯式的使用this作為主調,以表示對象的屬性,若不存在此問題,可以不顯式的寫this。

其實,其牽涉到的一個問題就是變數的尋找規則:先局部變數 => 當前類中定義的變數 => 其父類中定義的可以被子類繼承的變數 => 父類...

super表示調用父類中相應的屬性和方法。在方法中,若需要調用父類的方法時,也一定要寫在第一行

 

 

繼承與組合:

從單純的實現效果上看,繼承和組合都能達到同樣的目的。並且都是實現代碼複用的有效方式。

但在一般性的概念層次中,兩者具有較為明顯的差別。

繼承表現為一般——特殊的關係,子類是一個特殊的父類,是is-a的關係。父類具有所有子類的一般特性。

組合表現為整體——部分關係,即has-a關係。在組合中,通過將“部分”單獨抽取出來,形成自己的類定義,並且在“整體”

這個類定義中,將部分定義為其中的一個屬性,並通過get和set方法,以此可以調用“部分”類中的屬性和方法。

 

 

繼承的理解:

1、繼承是物件導向的三大特徵之一,也是實現代碼複用的重要手段。Java的繼承具有單繼承的特點,每個子類只有一個直接父類。

2、Java的繼承通過extends關鍵字來實現,實現繼承的類被稱為子類,被繼承的類稱為父類(有的也稱其為基類、超類),父類和子類的關係,是一種一般和特殊的關係。就像是水果和蘋果的關係,蘋果繼承了水果,蘋果是水果的子類,水果是蘋果的父類,則蘋果是一種特殊的水果。

3、Java使用extends作為繼承的關鍵字,extends關鍵字在英文是擴充的意思,而不是繼承。為什麼國內把extends翻譯成繼承呢?除了與曆史原因有關外,把extends翻譯成為繼承也是有其道理的:子類擴充父類,將可以獲得父類的全部屬性和方法,這與漢語中得繼承(子輩從父輩那裡獲得一筆財富成為繼承)具有很好的類似性。值得指出的是:Java的子類不能獲得父類的構造器。

 

eg:

class BaseClass{    public double weight;    public void info() {       System.out.println("我的體重是"+weight+"千克");    }} public class ExtendsDemo001 extends BaseClass {    public static void main(String[] args) {       //建立ExtendsDemo001對象       ExtendsDemo001 ed = new ExtendsDemo001();       //ExtendsDemo001本身沒有weight屬性,但是ExtendsDemo001的父類有weight屬性,也可以訪問ExtendsDemo001對象的屬性       ed.weight = 56;       //調用ExtendsDemo001對象的info()方法       ed.info();    }}

列印結果為:我的體重是56.0千克

 

 

 

Java類只能有一個父類。這句話是錯誤的,應該這樣說:Java類只能有一個直接父類,可以有無限多個間接父類

class  Fruit  extends  Plant{…….}class  Apple  extends  Fruit {…….}

 

Java基礎-四要素之一《繼承》

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.