Java繼承和多態(tài)


Java繼承和多態(tài)

繼承

定義

繼承就是利用現(xiàn)有類創(chuàng)建新類的過程惋鹅,現(xiàn)有的類稱為 父類(基類)持灰,新類稱為 子類(派生類)。比如現(xiàn)實(shí)中:兒子繼承了父親遺產(chǎn)一樣负饲。面向?qū)ο蟪绦蛟O(shè)計(jì)中的繼承堤魁,就是代碼重用。
Java中所有的類都繼承自 Object 這個(gè)父類返十。

實(shí)現(xiàn)

在Java中實(shí)現(xiàn)繼承需要使用到extends關(guān)鍵字妥泉;

[訪問修飾符] class 派生類名 extends 基類名 {
        成員列表
    }

如:

class Student extends Person
{
    ……
}

訪問修飾符 請(qǐng)參看之前章節(jié)的內(nèi)容。

例子

例:

定義抽象類:Person洞坑。

public abstract class Person {  // 抽象類
    private String name;  // 私有變量
    
    public String getName() {  // Getter方法
        return name;
    }
    public void setName(String name) {  //Setter方法
        this.name = name;
    }
        
    public Person(String name) {  // 構(gòu)造函數(shù)盲链,用于初始化name
        super();
        this.name = name;
    }
    public abstract String getDesc();  // 抽象類中的抽象方法。  只有聲明,沒有具體實(shí)現(xiàn)刽沾。
  
      public String toString(){      // toString方法覆蓋了Object類的toString方法
         return name + getDesc();
      }
}

public class Student extends Person {  // 繼承類
    private String major; // 新增加的數(shù)據(jù)    
    
    public String getMajor() {
        return major;
    }
    
    public void setMajor(String major) {
        this.major = major;
    }    
    
    public Student(String name,String major) { // 構(gòu)造函數(shù)用于初始化
        super(name);   // 調(diào)用超類構(gòu)造函數(shù)
        this.major = major;
    }
    
    @Override
    public String getDesc() {  // 必須實(shí)現(xiàn)超類中的抽象方法
        // TODO Auto-generated method stub
        return " : a student, major is " + major;
    }

繼承的作用

  • 當(dāng)今軟件設(shè)計(jì)的特征
    軟件規(guī)模越來越大
    軟件設(shè)計(jì)者越來越多
    軟件設(shè)計(jì)分工越來越細(xì)
  • 引入繼承本慕,實(shí)現(xiàn)了代碼重用;
  • 引入繼承侧漓,實(shí)現(xiàn)了遞增式的程序設(shè)計(jì)锅尘。
  • 繼承是能自動(dòng)傳播代碼和重用代碼的有力工具;
  • 繼承能夠在某些比較一般的類的基礎(chǔ)上建造布蔗、建立和擴(kuò)充新類藤违;
  • 能減少代碼和數(shù)據(jù)的重復(fù)冗余度,并通過增強(qiáng)一致性來減少模塊間的接口和界面纵揍,從而增強(qiáng)了程序的可維護(hù)性顿乒;
  • 能清晰地體現(xiàn)出類與類之間的層次結(jié)構(gòu)關(guān)系。

注意事項(xiàng)

  • 繼承是單方向的泽谨,即派生類可以繼承和訪問基類中的成員璧榄,但基類則無法訪問派生類中的成員; 父類不能訪問子類方法
  • 在Java中只允許 單一繼承 方式吧雹,即一個(gè)派生類只能繼承于一個(gè)基類犹菱,而不能象C++中派生類繼承于多個(gè)基類的多重繼承方式。

繼承中的構(gòu)造方法

  • 父類中的構(gòu)造方法可以被重載吮炕,但不能被子類繼承,即便它是public的访得;
  • 父類的構(gòu)造方法負(fù)責(zé)初始化屬于它的成員變量龙亲,而子類的構(gòu)造方法則只需考慮屬于自己的成員變量,不必去關(guān)注父類的情況悍抑。
  • 當(dāng)實(shí)例化子類的對(duì)象時(shí)鳄炉,必須先執(zhí)行父類的構(gòu)造方法,然后再執(zhí)行子類的構(gòu)造方法搜骡;
  • 如果父類還有更上級(jí)的父類拂盯,就會(huì)先調(diào)用最高父類的構(gòu)造方法,再逐個(gè)依次地將所有繼承關(guān)系的父類構(gòu)造方法全部執(zhí)行记靡;
  • 如果父類的構(gòu)造方法執(zhí)行失敗谈竿,那么子類的對(duì)象也將無法實(shí)例化。

class ParentClass {  //定義父類
  public ParentClass() {  //構(gòu)造方法
    System.out.println("這是父類的構(gòu)造方法摸吠。");
  }
}

class ChildClass extends ParentClass {  //子類繼承于父類
  public ChildClass() {  //構(gòu)造方法
    System.out.println("這是子類的構(gòu)造方法空凸。");
  }
}

public class ConstructorTest {  //該類用于容納main方法
  public static void main(String[] args) {
    ChildClass cc = new ChildClass();  //實(shí)例化子類對(duì)象
  }
}

super

如果子類需要調(diào)用父類的方法或者屬性怎么辦?

  • 在子類的構(gòu)造方法中寸痢,super關(guān)鍵字可以顯式地調(diào)用父類的構(gòu)造方法呀洲,用于將參數(shù)傳遞給它;需要注意的是: 該語句必須是子類構(gòu)造方法的第一條語句

如:

class Point  //定義"點(diǎn)"類
{
  protected float mX, mY;  //x軸坐標(biāo)和y軸坐標(biāo)

  public Point(float x, float y)  //構(gòu)造方法
  {
    mX = x;
    mY = y;
  }
  ……
}

class Circle extends Point  //定義"圓"類繼承于"點(diǎn)"類
{
  protected float mRadius;    //半徑

  public Circle(float x, float y, float r)  //構(gòu)造方法
  {
    super(x, y);  //顯式調(diào)用父類構(gòu)造方法,必須是第一條語句
    mRadius = r;
  }
  ……
}
  • 如果父類和子類中有同名成員道逗,在子類中默認(rèn)訪問是屬于自己的那一個(gè)成員兵罢;super關(guān)鍵字可以明確地指定要訪問父類中的成員;但前提條件是:父類中的該成員不是private的

多態(tài)

方法覆蓋

定義
  • 在類的繼承體系結(jié)構(gòu)中滓窍,如果子類中出現(xiàn)了與父類中有同原型的方法卖词,那么認(rèn)為子類中的方法覆蓋了父類中的方法(也稱為方法重寫);
  • 通過子類的實(shí)例調(diào)用被覆蓋的方法時(shí)贰您,將總是調(diào)用子類中的方法坏平,而父類中的方法將被隱藏。

如:

/*如果不但名稱相同锦亦,而且連方法原型也完全相同的話舶替,則構(gòu)成方法覆蓋*/
class ParentClass {  //定義父類
  public void fun() {
    System.out.println("這是父類中的方法。");
  }
}

class ChildClass extends ParentClass {//子類繼承于父類
  public void fun() {  //子類覆蓋父類中的方法
    System.out.println("這是子類中的方法杠园。");
  }
}

class OverriddenTest {  //用于容納main方法
  public static void main(String[] args) {
    ParentClass parObj = new ParentClass();
    parObj.fun();  //父類的實(shí)例調(diào)用此方法

    ChildClass chiObj = new ChildClass();
    chiObj.fun();  //子類的實(shí)例調(diào)用此方法
  }
}
方法覆蓋的注意事項(xiàng)
  • 子類中重寫的方法顾瞪,其訪問權(quán)限不能比父類中被重寫方法的訪問權(quán)限更低
  • 在子類中重寫方法時(shí)要保持方法的簽名與父類中方法的簽名一致

引用轉(zhuǎn)型

  • 基類(父類)的引用可以指向派生類(子類)的對(duì)象。

如:

BaseClass obj = new DerivedClass();
  • 如果存在方法覆蓋抛蚁,那么將會(huì)調(diào)用其派生類中的方法

如:

class Shapes {  //基本形狀類
  public void draw() {  //繪圖的方法
    System.out.println("繪制了一個(gè)基本形狀陈醒。");
  }
}
class Circle extends Shapes {  //圓形類繼承于基本形狀類
  public void draw() {  //覆蓋父類的繪圖方法
    System.out.println("繪制了一個(gè)圓形。");
  }
} 
class Square extends Shapes {  //正方形類繼承與基本形狀類
  public void draw() {  //覆蓋父類的繪圖方法
    System.out.println("繪制了一個(gè)正方形瞧甩。");
  }
}
public class polymorphismDemo {
  public static void main(String[] args) {
    Shapes obj = new Shapes();  //父類的引用指向父類的實(shí)例
    obj.draw();                 //調(diào)用繪圖方法
    obj = new Circle();         //父類的引用指向子類的實(shí)例
    obj.draw();                 //調(diào)用繪圖方法
    obj = new Square();         //父類的引用指向子類的實(shí)例
    obj.draw();                 //調(diào)用繪圖方法
  }
}

多態(tài)

在Java中钉跷,使用父類的引用,調(diào)用同一個(gè)方法肚逸,卻可以得到不同的調(diào)用結(jié)果爷辙,這就是多態(tài)。即: 同一函數(shù)朦促,多種形態(tài)膝晾。
實(shí)際上多態(tài)包括 動(dòng)態(tài)多態(tài)靜態(tài)多態(tài)

靜態(tài)多態(tài)
  • 靜態(tài)多態(tài)也稱為編譯時(shí)多態(tài)务冕,即在編譯時(shí)決定調(diào)用哪個(gè)方法血当;
  • 靜態(tài)多態(tài)一般是指方法重載;
  • 只要構(gòu)成了方法重載禀忆,就可以認(rèn)為形成了靜態(tài)多態(tài)的條件臊旭;
  • 靜態(tài)多態(tài)與是否發(fā)生繼承沒有必然聯(lián)系。
動(dòng)態(tài)多態(tài)

動(dòng)態(tài)多態(tài)也稱為運(yùn)行時(shí)多態(tài)箩退,即在運(yùn)行時(shí)才能確定調(diào)用哪個(gè)方法巍扛。
形成動(dòng)態(tài)多態(tài)必須具體以下條件:

  • 必須要有繼承的情況存在;
  • 在繼承中必須要有方法覆蓋乏德;
  • 必須由基類的引用指向派生類的實(shí)例撤奸,并且通過基類的引用調(diào)用被覆蓋的方法吠昭;

由上述條件可以看出,繼承是實(shí)現(xiàn)動(dòng)態(tài)多態(tài)的首要前提胧瓜。

抽象

抽象方法

基類無法(或者沒有必要)提供被覆蓋方法的具體實(shí)現(xiàn)矢棚,那么就可以將這個(gè)方法定義為 抽象方法

[訪問權(quán)限] abstract 返回值類型 方法名(參數(shù)列表){
}

如:

public abstract void draw(){
}
抽象類

如果某個(gè)類包含抽象方法府喳,那么這個(gè)類就必須定義成 抽象類蒲肋。

[訪問權(quán)限] abstract class 類名{
    成員列表
}

如:

public abstract class Shapes{
    public abstract void draw();
}
抽象類的注意事項(xiàng)
  • 抽象類不可以直接實(shí)例化,只可以用來繼承钝满;
  • 抽象類的派生子類應(yīng)該提供對(duì)其所有抽象方法的具體實(shí)現(xiàn)兜粘;
  • 如果抽象類的派生子類沒有實(shí)現(xiàn)其中的所有抽象方法,那么該派生子類仍然是抽象類弯蚜,只能用于繼承孔轴,而不能實(shí)例化;
  • 抽象類中也可以包含有非抽象的方法碎捺;
  • 構(gòu)造方法和靜態(tài)方法不可以修飾為abstract路鹰。

如:

abstract class Shapes {  //基本形狀類,抽象類
    public abstract void draw();  //繪圖方法收厨,抽象方法
}
class Circle extends Shapes {  //圓形類繼承于基本形狀類
    public void draw() {  //實(shí)現(xiàn)抽象父類的抽象繪圖方法
        System.out.println("繪制了一個(gè)圓形晋柱。");
    }
}
class Square extends Shapes {  //正方形類繼承與基本形狀類
    public void draw() {  //實(shí)現(xiàn)抽象父類的抽象繪圖方法
        System.out.println("繪制了一個(gè)正方形。");
    }
}
public class abstractDemo {  //該類用于容納main方法
    public static void main(String[] args) {
        Shapes obj;
        obj = new Circle();         //父類的引用指向子類的實(shí)例
        obj.draw();                 //調(diào)用繪圖方法
        obj = new Square();         //父類的引用指向子類的實(shí)例
        obj.draw();                 //調(diào)用繪圖方法
    }
}

接口

接口定義

如果某個(gè)類中所有的方法都是 抽象方法诵叁,那么可以考慮將該類定義為接口雁竞。

[訪問權(quán)限] interface 接口名{
    成員列表
}

如:

public interface IMyInterface{
    public void doIt();
}
實(shí)現(xiàn)接口

接口只能用于實(shí)現(xiàn),不能實(shí)例化(new)拧额。

[訪問權(quán)限] class 類名 implements 接口名 {
    成員列表
}

如:

public class MyClass implements IMyInterface {
    public void doIt(){
    }
}
接口的注意事項(xiàng)
  • 接口中不能定義非抽象方法碑诉,也就是說接口中不能包含有函數(shù)實(shí)體。
    接口中的所有方法都默認(rèn)為抽象方法势腮,無需在每個(gè)方法前加abstract關(guān)鍵字。
  • 接口的實(shí)現(xiàn)類應(yīng)該提供對(duì)接口中所有抽象方法的具體實(shí)現(xiàn)漫仆,否則將成為抽象類捎拯。
    與抽象類和它的繼承類相似,也可以使用接口的引用指向其實(shí)現(xiàn)類的對(duì)象盲厌,從而達(dá)到動(dòng)態(tài)多態(tài)的效果署照。
  • Java只支持單繼承,而不能象C++那樣可以多重繼承吗浩,接口正是為了彌補(bǔ)這一點(diǎn)建芙。
  • Java中還允許一個(gè)接口繼承于另一個(gè)接口,即由父接口派生出子接口懂扼。

如:

public interface 子接口名 extends 父接口名 {
    成員列表
}

final關(guān)鍵字

final修飾變量

如果將某個(gè)變量修飾為final禁荸,那么該變量就成為 常量
如:

final double PI = 3.14159;

☆ 常量在聲明時(shí)必須初始化右蒲。

final修飾方法

如果將某個(gè)成員方法修飾為final,則意味著該方法 不能被子類覆蓋
如:

public final void fun() {
    ……
}
//如果在派生類中出現(xiàn)同原型的方法赶熟,將會(huì)報(bào)錯(cuò)瑰妄。
final修飾類

如果將某個(gè)類修飾為final,則說明該類 無法被繼承
如:

public final class MyClass {
    ……
}
//任何類想繼承于MyClass類都將報(bào)錯(cuò)映砖。

類和類之間的關(guān)系

  • 有——>has
    汽車有輪子间坐。一般來說這種關(guān)系對(duì)應(yīng)的是 屬性

  • 是——>is
    圓形是個(gè)形狀邑退。一般來說這種關(guān)系對(duì)應(yīng)的是 方法竹宋。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市地技,隨后出現(xiàn)的幾起案子蜈七,更是在濱河造成了極大的恐慌,老刑警劉巖乓土,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宪潮,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡趣苏,警方通過查閱死者的電腦和手機(jī)狡相,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來食磕,“玉大人尽棕,你說我怎么就攤上這事”蚵祝” “怎么了滔悉?”我有些...
    開封第一講書人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長单绑。 經(jīng)常有香客問我回官,道長,這世上最難降的妖魔是什么搂橙? 我笑而不...
    開封第一講書人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任歉提,我火速辦了婚禮,結(jié)果婚禮上区转,老公的妹妹穿的比我還像新娘苔巨。我一直安慰自己,他們只是感情好废离,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開白布侄泽。 她就那樣靜靜地躺著,像睡著了一般蜻韭。 火紅的嫁衣襯著肌膚如雪悼尾。 梳的紋絲不亂的頭發(fā)上柿扣,一...
    開封第一講書人閱讀 51,521評(píng)論 1 304
  • 那天,我揣著相機(jī)與錄音诀豁,去河邊找鬼窄刘。 笑死,一個(gè)胖子當(dāng)著我的面吹牛舷胜,可吹牛的內(nèi)容都是我干的娩践。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼烹骨,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼翻伺!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起沮焕,我...
    開封第一講書人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤吨岭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后峦树,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辣辫,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年魁巩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了急灭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谷遂,死狀恐怖葬馋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情肾扰,我是刑警寧澤畴嘶,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站集晚,受9級(jí)特大地震影響窗悯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜偷拔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一蒋院、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧条摸,春花似錦悦污、人聲如沸铸屉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽彻坛。三九已至顷啼,卻和暖如春踏枣,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背钙蒙。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來泰國打工茵瀑, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人躬厌。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓马昨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親扛施。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鸿捧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 本文出自 Eddy Wiki ,轉(zhuǎn)載請(qǐng)注明出處:http://eddy.wiki/interview-java.h...
    eddy_wiki閱讀 1,202評(píng)論 0 5
  • 繼承和多態(tài) 1. 繼承的優(yōu)缺點(diǎn) 優(yōu)點(diǎn):(1)子類可以靈活地改變父類中的已有方法疙渣;(2)能夠最大限度的實(shí)現(xiàn)代碼重用匙奴。...
    MinoyJet閱讀 625評(píng)論 0 0
  • (一)Java部分 1、列舉出JAVA中6個(gè)比較常用的包【天威誠信面試題】 【參考答案】 java.lang;ja...
    獨(dú)云閱讀 7,104評(píng)論 0 62
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法妄荔,類相關(guān)的語法泼菌,內(nèi)部類的語法,繼承相關(guān)的語法啦租,異常的語法哗伯,線程的語...
    子非魚_t_閱讀 31,631評(píng)論 18 399
  • 昨天笋颤,我的大學(xué)室友給我發(fā)來一屏幕的微信語音 大致的意思是,她有一個(gè)又丑又丑的同學(xué)内地,通過整容把自己變成白富美伴澄,還有一...
    呼啦來了閱讀 486評(píng)論 0 0