欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java基礎(chǔ)教程之繼承詳解

 更新時間:2014年08月31日 17:21:06   投稿:junjie  
這篇文章主要介紹了Java基礎(chǔ)教程之繼承詳解,繼承是除組合(composition)之外,提高代碼重復(fù)可用性(reusibility)的另一種重要方式,本文對繼承做了詳細(xì)講解,需要的朋友可以參考下

繼承(inheritance)是面向?qū)ο蟮闹匾拍?。繼承是除組合(composition)之外,提高代碼重復(fù)可用性(reusibility)的另一種重要方式。我們在組合(composition)中看到,組合是重復(fù)調(diào)用對象的功能接口。我們將看到,繼承可以重復(fù)利用已有的類的定義。

類的繼承

我們之前定義類的時候,都是從頭開始,詳細(xì)的定義該類的每一個成員。比如下面的Human類:

復(fù)制代碼 代碼如下:

class Human
{  
   /**
     * accessor
     */
    public int getHeight()
    {
       return this.height;
    }

    /**
     * mutator
     */
    public void growHeight(int h)
    {
        this.height = this.height + h;
    }

    /**
     * breath
     */
    public void breath()
    {
        System.out.println("hu...hu...");
    }

    private int height;
}

從上面的類定義,我們可以了解該類的所有細(xì)節(jié): 該類的數(shù)據(jù)成員,該類的方法,該類的接口。

現(xiàn)在要定義一個新的類,比如Woman類,并假設(shè)Woman與Human類相當(dāng)類似:


Human & Woman

我們可以像以前一樣,從頭開始,完整的定義Woman類:

復(fù)制代碼 代碼如下:

class Woman
{
    /**
     * accessor
     */
    public int getHeight()
    {
       return this.height;
    }

    /**
     * mutator
     */
    public void growHeight(int h)
    {
        this.height = this.height + h;
    }


    /**
     * breath
     */
    public void breath()
    {
        System.out.println("hu...hu...");
    }

    /**
     * new method
     */
    public Human giveBirth()
    {
        System.out.println("Give birth");
        return (new Human(20));
    }

    private int height;
}

一個程序員在寫上面程序的時候,會有很大的煩惱。許多定義都曾在Human類中寫過,但我們還要重新敲一遍。Woman類只新增了一個giveBirth()方法 (該方法創(chuàng)建并返回一個新的Human對象)。

利用繼承,我們可以避免上面的重復(fù)。讓W(xué)oman類繼承自Human類,Woman類就自動擁有了Human類中所有public成員的功能。

我們用extends關(guān)鍵字表示繼承:

復(fù)制代碼 代碼如下:

class Woman extends Human
{
    /**
     * new method
     */
    public Human giveBirth()
    {
        System.out.println("Give birth");
        return (new Human(20));
    }
}

這樣,我們就省去了大量的輸入。通過繼承,我們創(chuàng)建了一個新類,叫做衍生類(derived class)。被繼承的類(Human)稱為基類(base class)。衍生類以基類作為自己定義的基礎(chǔ),并補充基類中沒有定義的giveBirth()方法。繼承關(guān)系可以表示為:

繼承: 箭頭指向基類

可以用以下Test類測試:

復(fù)制代碼 代碼如下:

public class Test
{
    public static void main(String[] args)
    {
        Woman aWoman = new Woman();
        aWoman.growHeight(120);
        System.out.println(aWoman.getHeight());                                            
    }
}

衍生層

通過繼承,我們創(chuàng)建了Woman類。整個過程可以分為三個層次: 基類定義,衍生類定義,外部使用。

基類定義的層次就是正常的定義一個類,比如上面的Human類定義。

在外部使用者看來(比如Test類中創(chuàng)建Woman類對象),衍生類有一個統(tǒng)一的外部接口:

對于外部使用者來說,上述接口就已經(jīng)足夠了。僅從接口看,衍生類也沒有什么特別之處。

 然而,當(dāng)程序員在衍生類定義的層次時,就必須要小心:

首先,接口是混合的: getHeight()方法和growHeight()方法來自基類,giveBirth()方法則是在衍生類內(nèi)部定義的。

還有更加復(fù)雜的地方。我們之前在類的內(nèi)部可以自由訪問類的成員(利用this指代對象)。然而,當(dāng)我們在Woman類的定義范圍內(nèi),我們無法訪問基類Human的private成員。我們記得private的含義: private的成員僅供該類內(nèi)部使用。Woman類是一個不同于Human類的新類,所以位于Human類的外部。在衍生類中,不能訪問基類的private成員。

但有趣的是,我們的growHeight()和getHeight()方法依然可以運行。這說明基類的private成員存在,我們只是不能直接訪問。

為了清晰概念,我們需要了解衍生類對象的生成機制。當(dāng)我們創(chuàng)建一個衍生類的對象時,Java實際上先創(chuàng)建了一個基類對象(subobject),并在基類對象的外部(注意,這里是基類對象的外部,衍生類對象的內(nèi)部),增加衍生類定義的其他成員,構(gòu)成一個衍生類對象。外部使用者能看到的,就是基類和衍生類的public成員。如下圖:

基類對象與衍生類對象

圖中黃色為基類對象?;鶎拥某蓡T之間可以互相訪問 (利用Human類定義中的this指代基類對象)。

藍(lán)色部分為衍生對象新增的內(nèi)容,我將這部分稱為衍生層。藍(lán)色和黃色部分共同構(gòu)成衍生對象。衍生層的成員可以相互訪問(Woman定義中的this)。更進(jìn)一步,我們還可以訪問基層中public的成員。為此,我們用super關(guān)鍵字來指代基類對象,使用super.member的方式來表示基層的(public)成員。

當(dāng)我們位于衍生層時(也就是在定義Woman類時),不能訪問紅色的基層private成員。當(dāng)我們位于外部時,既不能訪問紫色的衍生層private成員,也不能訪問紅色的基層private成員。

(衍生層的private成員有訪問禁忌,所以標(biāo)為斜線?;鶎拥膒rivate成員訪問禁忌最多,所以標(biāo)為交叉斜線)

super和this類似,也是隱式參數(shù)。我們在類定義的不同層次時,this會有不同的含義。要小心的使用this和super關(guān)鍵字。

(Java并不強制使用this和super。Java在許多情況下可以自動識別成員的歸屬。但我覺得這是個好習(xí)慣。)

protected

我們之前介紹了兩個訪問權(quán)限相關(guān)的關(guān)鍵字,private和public,它們控制了成員的外部可見性?,F(xiàn)在,我們介紹一個新的訪問權(quán)限關(guān)鍵字: protected。

標(biāo)為protected的成員在該類及其衍生類中可見。這個概念很容易理解,就是說,基類的protected成員可以被衍生層訪問,但不能被外部訪問,如下圖:

方法覆蓋

衍生類對象的外部接口最終由基類對象的public成員和衍生層的public成員共同構(gòu)成。如果基類public成員和衍生層的public成員同名,Java接口中呈現(xiàn)的究竟是哪一個呢?

我們在構(gòu)造方法與方法重載中已經(jīng)提到,Java是同時通過方法名和參數(shù)列表來判斷所要調(diào)用的方法的。方法是由方法名和參數(shù)列表共同決定的。上述問題中,如果只是方法名相同,而參數(shù)列表不同,那么兩個方法會同時呈現(xiàn)到接口,不會給我們造成困擾。外部調(diào)用時,Java會根據(jù)提供的參數(shù),來決定使用哪個方法 (方法重載)。

如果方法名和參數(shù)列表都相同呢? 在衍生層時,我們還可以通過super和this來確定是哪一個方法。而在外部時,我們呈現(xiàn)的只是統(tǒng)一接口,所以無法同時提供兩個方法。這種情況下,Java會呈現(xiàn)衍生層的方法,而不是基層的方法。

這種機制叫做方法覆蓋(method overriding)。方法覆蓋可以被很好的利用,用于修改基類成員的方法。比如,在衍生層,也就是定義Woman時,可以修改基類提供的breath()方法:

復(fù)制代碼 代碼如下:

class Woman extends Human
{/**
     * new method
     */
    public Human giveBirth()
    {
        System.out.println("Give birth");
        return (new Human(20));
    }

    /**
     * override Human.breath()
     */
    public void breath()
    {
        super.breath();
        System.out.println("su...");
    }
}

注意,此時我們位于衍生層,依然可以通過super來調(diào)用基類對象的breath()方法。當(dāng)我們外部調(diào)用Woman類時,由于方法覆蓋,就無法再調(diào)用基類對象的該方法了。

方法覆蓋保持了基類對象的接口,而采用了衍生層的實現(xiàn)。

構(gòu)造方法

在了解了基類對象和衍生層的概念之后,衍生類的構(gòu)造方法也比較容易理解。

我們要在衍生類的定義中定義與類同名的構(gòu)造方法。在該構(gòu)造方法中:

1.由于在創(chuàng)建衍生對象的時候,基類對象先被創(chuàng)建和初始化,所以,基類的構(gòu)造方法應(yīng)該先被調(diào)用。我們可以使用super(argument list)的語句,來調(diào)用基類的構(gòu)造方法。

2.基類對象創(chuàng)建之后,開始構(gòu)建衍生層 (初始化衍生層成員)。這和一般的構(gòu)建方法相同,參考構(gòu)造方法與方法重載

比如下面的程序中,Human類有一個構(gòu)造方法:

復(fù)制代碼 代碼如下:

class Human
{  

    /**
     * constructor
     */
    public Human(int h)
    {
        this.height = h;
    }

    /**
     * accessor
     */
    public int getHeight()
    {
       return this.height;
    }

    /**
     * mutator
     */
    public void growHeight(int h)
    {
        this.height = this.height + h;
    }

    /**
     * breath
     */
    public void breath()
    {
        System.out.println("hu...hu...");
    }

    private int height;
}

衍生類Woman類的定義及其構(gòu)造方法:

復(fù)制代碼 代碼如下:

class Woman extends Human
{
    /**
     * constructor
     */
    public Woman(int h)
    {
        super(h); // base class constructor
        System.out.println("Hello, Pandora!");
    }

    /**
     * new method
     */
    public Human giveBirth()
    {
        System.out.println("Give birth");
        return (new Human(20));
    }

    /**
     * override Human.breath()
     */
    public void breath()
    {
        super.breath();
        System.out.println("su...");
    }
}

總結(jié)

extends

method overriding

protected

super.member, super()

相關(guān)文章

  • SpringBoot上傳文件大小受限問題的解決辦法

    SpringBoot上傳文件大小受限問題的解決辦法

    最近有一次由于項目升級發(fā)現(xiàn)了一個上傳方面的問題,下面這篇文章主要給大家介紹了關(guān)于SpringBoot上傳文件大小受限問題的解決辦法,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-05-05
  • Spring Boot JPA中使用@Entity和@Table的實現(xiàn)

    Spring Boot JPA中使用@Entity和@Table的實現(xiàn)

    這篇文章主要介紹了Spring Boot JPA中使用@Entity和@Table的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • Java實現(xiàn)圖片拼接

    Java實現(xiàn)圖片拼接

    這篇文章主要為大家詳細(xì)介紹了Java實現(xiàn)圖片拼接的相關(guān)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • 淺談spring注解之@profile

    淺談spring注解之@profile

    這篇文章主要介紹了淺談spring注解之@profile,@profile通過配置來改變參數(shù),這里整理的詳細(xì)的用法,有興趣的可以了解一下
    2017-10-10
  • Java并發(fā)編程之原子性-Atomic的使用

    Java并發(fā)編程之原子性-Atomic的使用

    這篇文章主要介紹了Java并發(fā)編程之原子性-Atomic的使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java通過PowerMockito和Mokito進(jìn)行單元測試的實現(xiàn)

    Java通過PowerMockito和Mokito進(jìn)行單元測試的實現(xiàn)

    PowerMockito和Mockito都是Java語言中的測試框架,用于進(jìn)行單元測試和集成測試,本文就來詳細(xì)的介紹一下通過PowerMockito和Mokito進(jìn)行單元測試,感興趣的可以了解一下
    2023-08-08
  • Mybatis Trim標(biāo)簽用法簡單介紹

    Mybatis Trim標(biāo)簽用法簡單介紹

    這篇文章主要介紹了Mybatis Trim標(biāo)簽用法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-05-05
  • SSM整合中的Log4j日志的配置詳情

    SSM整合中的Log4j日志的配置詳情

    這篇文章主要介紹了SSM整合中的Log4j的配置詳情,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • SpringBoot項目中連接SQL Server的三種方式

    SpringBoot項目中連接SQL Server的三種方式

    連接SQL Server是許多Spring Boot項目中常見的需求之一,本文主要介紹了SpringBoot項目中連接SQL Server的三種方式,具有一定的參考價值 ,感興趣的可以了解一下
    2023-09-09
  • SpringBoot 文件上傳和下載的實現(xiàn)源碼

    SpringBoot 文件上傳和下載的實現(xiàn)源碼

    這篇文章主要介紹了SpringBoot 文件上傳和下載的實現(xiàn)源碼,代碼簡單易懂非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2018-04-04

最新評論