多態(tài)

多態(tài)就是對(duì)象的多種形態(tài),即相同的消息使得不同的類做出不同的響應(yīng)。

多態(tài)存在的三個(gè)必要條件:繼承、重寫、父類變量引用子類對(duì)象(向上轉(zhuǎn)型)。

實(shí)現(xiàn)多態(tài)的技術(shù)稱為動(dòng)態(tài)綁定,是指在執(zhí)行期間判斷所引用對(duì)象的實(shí)際類型,根據(jù)其實(shí)際的類型調(diào)用其相應(yīng)的方法。

Java中多態(tài)的實(shí)現(xiàn)方式:接口實(shí)現(xiàn),繼承父類進(jìn)行方法重寫,同一個(gè)類中進(jìn)行方法重載

對(duì)象和對(duì)象引用

new關(guān)鍵字

創(chuàng)建一個(gè)Java對(duì)象需要三部:聲明引用變量、實(shí)例化、初始化對(duì)象實(shí)例。

①聲明引用變量

聲明一個(gè)變量來指向一個(gè)對(duì)象,即引用

要聲明一個(gè)變量,需要寫:Animal animal;

這將告訴編譯器你將使用animal引用一個(gè)Animal類型的對(duì)象。用一個(gè)原始變量,這個(gè)聲明也保留了適當(dāng)?shù)膬?nèi)存量的變量。

②實(shí)例化

new運(yùn)算符實(shí)例化一個(gè)類對(duì)象,通過給這個(gè)對(duì)象分配內(nèi)存并返回一個(gè)指向該內(nèi)存的引用。

“實(shí)例化一個(gè)類的對(duì)象”的意思就是“創(chuàng)建對(duì)象”。創(chuàng)建對(duì)象時(shí),你正在創(chuàng)造一個(gè)類的“實(shí)例”,因而“實(shí)例化”一個(gè)類的對(duì)象。

③初始化對(duì)象實(shí)例

就是調(diào)用構(gòu)造方法,對(duì)類的實(shí)例數(shù)據(jù)賦初值。構(gòu)造函數(shù)的名稱提供了需要實(shí)例化類的名稱。

對(duì)象

對(duì)象是類的一個(gè)實(shí)例,創(chuàng)建對(duì)象的過程也叫做類的實(shí)例化。

如人類是一個(gè)類,那么我們每一個(gè)具體的人就是這個(gè)類的對(duì)象。

對(duì)象引用

我們知道new關(guān)鍵字是一個(gè)java運(yùn)算符,它用來創(chuàng)建對(duì)象

Animal animal; ?//聲明一個(gè)變量來指向一個(gè)對(duì)象,即引用

animal = new A animal();

如上代碼,創(chuàng)建對(duì)象的語句是new Animal(),那么animal又是什么呢?animal只是一個(gè)引用,是指向一個(gè)對(duì)象的引用,這個(gè)對(duì)象指向Animal類。也就是說,Animal animal 這句話只是聲明了一個(gè)Animal類的引用,它可以指向任何Animal類的實(shí)例。

一個(gè)引用可以指向多個(gè)對(duì)象,而一個(gè)對(duì)象也可以被多個(gè)引用所指。

引用多態(tài)

父類的引用可以指向本類的對(duì)象 ? Animal animal=new Animal();

父類的引用可以指向子類的對(duì)象 ?Animal animal=new Dog();

注意:父類的引用指向子類的對(duì)象時(shí),子類中特有的方法和屬性就不能使用了。

方法多態(tài)

創(chuàng)建本類對(duì)象時(shí),調(diào)用的方法為本類方法

創(chuàng)建子類對(duì)象時(shí),調(diào)用的方法為子類重寫的方法或者繼承的方法(不能為子類特有的)

類型轉(zhuǎn)換

多態(tài)中的類型轉(zhuǎn)換是基于存在繼承關(guān)系的對(duì)象,有向上類型轉(zhuǎn)換和向下類型轉(zhuǎn)換。

向上轉(zhuǎn)型:父類的引用可以指向子類的對(duì)象

如 Animal animal=new Dog(); ?//Animal類是Dog類的父類

Dog對(duì)象實(shí)例被向上轉(zhuǎn)型成了animal,但Dog對(duì)象實(shí)例本質(zhì)上還是Dog類型,只不過能力被暫時(shí)削弱了

向下轉(zhuǎn)型:向上轉(zhuǎn)型之后子類特有的方法和屬性就不能被調(diào)用了,有時(shí)我們想用這些方法和屬性,就需要將向上轉(zhuǎn)型后的子類對(duì)象再轉(zhuǎn)成子類,調(diào)用子類的方法

如 Dog dog=(Dog)animal;

animal的引用仍然是Animal類型,只不過功能增強(qiáng)了,然后交給dog引用

注:不能直接將父類對(duì)象強(qiáng)制轉(zhuǎn)換為子類類型,只能將向上轉(zhuǎn)型后的子類對(duì)象在此轉(zhuǎn)為子類類型。

向上轉(zhuǎn)型就好比把茶杯里的水往茶壺中倒,是安全的;向下轉(zhuǎn)型就是把茶壺里的水往茶杯里倒,會(huì)存在風(fēng)險(xiǎn),instanceof運(yùn)算符就可以避免類型轉(zhuǎn)換的安全問題了。

instanceof就是去判斷向下轉(zhuǎn)型的對(duì)象將要轉(zhuǎn)換的類型是不是這個(gè)對(duì)象的類型

如:Animal animal = new Dog();//父類引用指向了子類的對(duì)象

?????? Dog dog = (Dog)animal;//將子類對(duì)象的引用類型轉(zhuǎn)成子類,用一個(gè)子類類型的引用來接收

?????? Cat cat = (Cat)animal;//編譯器不報(bào)錯(cuò),但是animal是Dog類的對(duì)象,在運(yùn)行時(shí)會(huì)報(bào)錯(cuò),此時(shí)需要用instanceof去判斷一下

instanceof運(yùn)算符用法:左邊的操作元是一個(gè)對(duì)象,右邊是一個(gè)類。如果左邊的對(duì)象是右邊類的實(shí)例,該運(yùn)算符運(yùn)算的結(jié)果是true,否則是false

注意:一個(gè)類的實(shí)例包括本身的實(shí)例,以及所有直接或間接子類的實(shí)例

? ? ? ? ? instanceof左邊對(duì)象的類型(注意是它引用的對(duì)象的類型,不是變量的類型)與右邊必須是同種類或是繼承關(guān)系

class Animal{ }

class Dog extends Animal{ }


public class Test {

? ?public static void main(String[] args) {

? ? ? ?Animal animal=new Dog(); //向上轉(zhuǎn)型

? ? ? ?if(animal instanceof Dog){

? ? ? ? ? ?Dog dog=(Dog)animal; //向下轉(zhuǎn)型

? ? ? ?}

? ? ? ?else

? ? ? ? ? ?System.out.println("不能轉(zhuǎn)換");

? ?}

}


一個(gè)經(jīng)典的例子

public class A {

??? public String show(D obj) {

??? return ("A and D");

??? }

??? public String show(A obj) {

??? return ("A and A");

??? }

}


public class B extends A{

??? public String show(B obj){

??????? return ("B and B");

??? }

??? public String show(A obj){

??????? return ("B and A");

??? }

}


public class C extends B{ }

public class D extends B{ }


public class Test {

??? public static void main(String[] args) {

??????? A a1 = new A();

??????? A a2 = new B();

??????? B b = new B();

??????? C c = new C();

??????? D d = new D();

??????? System.out.println("1--" + a1.show(b));

??????? System.out.println("2--" + a1.show(c));

??????? System.out.println("3--" + a1.show(d));

??????? System.out.println("4--" + a2.show(b));

??????? System.out.println("5--" + a2.show(c));

??????? System.out.println("6--" + a2.show(d));

??????? System.out.println("7--" + b.show(b));

??????? System.out.println("8--" + b.show(c));

??????? System.out.println("9--" + b.show(d));

??? }

}

運(yùn)行結(jié)果:

1--A and A

2--A and A

3--A and D

4--B and A

5--B and A

6--A and D

7--B and B

8--B and B

9--A and D

抽象類和接口

1.抽象類

當(dāng)父類只知道子類的方法而不知道子類的方法如何實(shí)現(xiàn)時(shí)可以將子類定義為抽象類,若多個(gè)類都有一個(gè)共同的方法,則可以將它抽象成一個(gè)抽象類

抽象方法是一種特殊的方法,它只有聲明,沒有具體的實(shí)現(xiàn)(即方法體),以分號(hào)結(jié)束

如:abstract void fun();

如果一個(gè)類含有抽象方法,那這個(gè)類就是抽象類

抽象類中可以有普通方法和抽象方法

抽象類和抽象方法前面必須都有abstract修飾,因?yàn)槌橄箢愔袥]有具體實(shí)現(xiàn)的方法,所以抽象類不能被實(shí)例化,實(shí)例化的工作交由子類去完成,它只需要有一個(gè)引用即可

抽象類就是為了繼承實(shí)現(xiàn)的,如果一個(gè)類繼承了抽象類,那么子類必須實(shí)現(xiàn)父類的抽象方法,如果子類沒有繼承父類的抽象方法,那么子類就必須也定義為抽象類

抽象方法必須為public或protected,如果沒有訪問控制符的話,默認(rèn)為public

如果子類也是一個(gè)抽象類的話,可以不用實(shí)現(xiàn)父類的抽象方法,如果子類不是一個(gè)抽象類的話,就必須實(shí)現(xiàn)父類的抽象方法

2.接口

一個(gè)類只能extends一個(gè)父類,但可以implements多個(gè)接口,java通過接口的概念來實(shí)現(xiàn)c++中的多繼承。一個(gè)接口可以同時(shí)extends多個(gè)接口,卻不能implements任何接口,因而,Java中的接口是支持多繼承的。

接口是由全局常量和公共的抽象方法所組成。

接口是要被繼承實(shí)現(xiàn)的,所以不能用private和protected修飾,一般用public

接口中可以含有變量和方法,但接口中的變量會(huì)被隱式的指定為public static final(并且只能是public static final),因?yàn)榻涌谥械膶傩允浅A?。方法?huì)被隱式的指定為public abstract(并且只能是public abstract),因?yàn)榻涌谥兴械姆椒ú荒苡芯唧w的實(shí)現(xiàn),即這些方法必須都為抽象方法

允許一個(gè)類遵循多個(gè)接口

如果一個(gè)非抽象類遵循了某個(gè)接口,則這個(gè)類必須實(shí)現(xiàn)接口中的所有方法,如果一個(gè)抽象類遵循了某個(gè)接口。則可以不實(shí)現(xiàn)該接口中的方法

3.抽象類和接口的區(qū)別

抽象類中可以有普通的方法,接口中只能有抽象方法

抽象類中的成員變量可以使各種類型的,而接口中必須是public static final型的

接口中不能含有靜態(tài)代碼塊以及靜態(tài)方法,抽象類中可以有

一個(gè)類只能繼承一個(gè)抽象類,而一個(gè)類可以遵循多個(gè)接口

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一.成員變量與局部變量的區(qū)別 成員變量:在類中定義,用來描述對(duì)象將要有什么(屬性)??杀槐绢惙椒ê推渌?dāng)前類有關(guān)...
    jeffierw閱讀 644評(píng)論 0 0
  • 1.面向?qū)ο笕筇匦?-封裝性 -繼承性 -多態(tài)性 2.什么是封裝 封裝性就是隱藏實(shí)現(xiàn)細(xì)節(jié),僅對(duì)外公開接口。 3....
    夢夜繁星閱讀 1,176評(píng)論 0 6
  • 多態(tài):對(duì)象的多種形態(tài) 1、引用多態(tài) 父類的引用可以指向本類的對(duì)象父類的引用可以指向子類的對(duì)象 2、方法多態(tài) 創(chuàng)建本...
    少冰三hun甜閱讀 1,132評(píng)論 0 0
  • 第2章 多態(tài)2.1 多態(tài)概述多態(tài)是繼封裝、繼承之后,面向?qū)ο蟮牡谌筇匦浴,F(xiàn)實(shí)事物經(jīng)常會(huì)體現(xiàn)出多種形態(tài),如學(xué)生,學(xué)...
    葡小萄家的貓閱讀 3,400評(píng)論 1 6
  • 【連載】《堇萱枌榆》總目錄 【連載】《堇萱枌榆》第二十章:琴聲殺機(jī) 一睜開眼,就看到柏桁關(guān)切又擔(dān)憂的眼神,再看一眼...
    水輕揚(yáng)閱讀 393評(píng)論 3 6

友情鏈接更多精彩內(nèi)容