欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報激活碼778899分享:開發(fā)語言 Java之多態(tài)

柚子快報激活碼778899分享:開發(fā)語言 Java之多態(tài)

http://yzkb.51969.com/

一、多態(tài)前言

1.為什么要使用多態(tài)

Java中使用多態(tài)的主要目的是提高代碼的可重用性和擴(kuò)展性,使得代碼更加靈活和易于維護(hù)。通過多態(tài),我們可以將不同的對象看做是同一種類型,從而使得我們可以使用同一種接口來操作這些對象,而不必關(guān)心具體的實現(xiàn)細(xì)節(jié)。

2.多態(tài)概念

當(dāng)父類的引用所指向的子類對象引用指向的對象不一樣時。調(diào)用重寫的方法,所表現(xiàn)出來的行為是不一樣的,我們把這種思想叫做多態(tài)。上面所說的可能大家會覺得有點抽象,看到后面就懂了。 多態(tài)的基礎(chǔ)是動態(tài)綁定,所以要了解多態(tài)前提我們還要了解動態(tài)綁定。 要想實現(xiàn)動態(tài)綁定,需要滿足以上幾個條件: 1.要發(fā)生向上轉(zhuǎn)型 2.要發(fā)生重寫 3.使用父類對象的引用去調(diào)用重寫方法 完成了這三部分,就會發(fā)生動態(tài)綁定,而在這里,出現(xiàn)了重寫以及向上轉(zhuǎn)型這些概念。所以我們得先了解它們才能去了解動態(tài)綁定。進(jìn)而了解多態(tài)。

二、重寫

1.重寫的概念

重寫

(override)

:也稱為覆蓋。將父類的方法重新在子類中使用。

返回值和形參都不能改變

。

即外殼不變,核心重寫!

重寫的好處在于子類可以根據(jù)需要,定義特定于自己的行為。 也就是說子類能夠根據(jù)需要實現(xiàn)父類的方法。

方法重寫的規(guī)則:1.子類在重寫父類的方法時,必須與父類方法原型一致:即返回值、方法名、參數(shù)列表要完全一致 2.被重寫的方法的訪問修飾限定符在子類中要大于等于父類的。 3.父類中被static或private或final修飾的方法以及構(gòu)造方法都不能被重寫。? 4.在子類中重寫的方法, 可以使用 @Override 注解來顯式指定. 有了這個注解能幫我們進(jìn)行一些合法性校驗。

2.重寫的作用

對于已經(jīng)投入使用的類,盡量不要進(jìn)行修改。最好的方式是:重新定義一個新的類,來重復(fù)利用其中共性的內(nèi)容,并且添加或者改動新的內(nèi)容。

例如:若干年前的手機,只能打電話,發(fā)短信,來電顯示只能顯示號碼,而今天的手機在來電顯示的時候,不僅僅可以顯示號碼,還可以顯示頭像,地區(qū)等。在這個過程當(dāng)中,我們不應(yīng)該在原來老的類上進(jìn)行修改,因為原來的

類,可能還在有用戶使用

,正確做法是:

新建一個新手機的類,對來電顯示這個方法重寫就好了,這樣就達(dá)到了我

們當(dāng)今的需求了

。

三、向上轉(zhuǎn)型

向上轉(zhuǎn)型:實際就是創(chuàng)建一個子類對象,將其當(dāng)成父類對象來使用。 語法格式:父類類型 對象名

= new

子類類型

()

Animal animal

=

Dog

(

);

我們對以上代碼進(jìn)行實質(zhì)化分析,以上的代碼其實是省略化了,見以下代碼

Dog dog = new Dog(); ?Animal animal = dog;//該代碼發(fā)生了向上轉(zhuǎn)換,將Dog對象轉(zhuǎn)換為Animal類型

通過向上轉(zhuǎn)型后,就可以父類對象名來訪問子類的方法了。使用animal.eat();這語句來訪問

這個語句發(fā)生了動態(tài)綁定(在編譯過程中調(diào)用的其實是父類的eat,但是在運行時換為調(diào)用子類的eat了)故實現(xiàn)了

創(chuàng)建一個子類對象,將其當(dāng)成父類對象來使用。見以下代碼

class Animal {

void sound() {

System.out.println("Animal makes a sound");

}

}

class Dog extends Animal {

?void sound() {

System.out.println("Dog barks");

}

?void fetch() {

System.out.println("Dog fetches a ball");

}

}

public class Main {

public static void main(String[] args) {

Dog dog = new Dog(); // 創(chuàng)建Dog對象

?Animal animal = dog; // 向上轉(zhuǎn)型,將Dog對象轉(zhuǎn)換為Animal類型

?animal.sound();//調(diào)用子類的覆蓋方法

?// animal.fetch(); // 編譯錯誤,因為Animal類中沒有fetch方法

}

}

// 輸出: Dog barks

通過以上代碼發(fā)現(xiàn)一個問題,不能調(diào)用到子類特有的方法(因為編譯時調(diào)用的是父類的方法),我們可以通過向下轉(zhuǎn)型來調(diào)用到子類特有的方法(后面介紹)靜態(tài)綁定:也稱為前期綁定(早綁定),即在編譯時,根據(jù)用戶所傳遞實參類型就確定了具體調(diào)用那個方法。典型代表函數(shù)重載。 動態(tài)綁定:也稱為后期綁定(晚綁定),即在編譯時,不能確定方法的行為,需要等到程序運行時,才能夠確定具體調(diào)用那個類的方法。當(dāng)發(fā)生重寫時,通過父類調(diào)用該方法時會發(fā)生動態(tài)綁定。

【向上轉(zhuǎn)型

使用場景

1.

直接賦值

2.

方法傳參

3.

方法返回

見以下代碼

public class TestAnimal {

// 2. 方法傳參:形參為父類型引用,可以接收任意子類的對象

public static void eatFood(Animal a){ //因為主方法的原因使用靜態(tài)方法

a.eat();? //方法傳參向上轉(zhuǎn)型

}

// 3. 作返回值:返回任意子類對象的實例

public static Animal buyAnimal(String var){

return new Dog();

}

public static void main() {

Animal cat = new Cat("元寶",2); // 1. 直接賦值:子類對象賦值給父類對象

Dog dog = new Dog("小七", 1);

animal.eat();? //直接賦值向上轉(zhuǎn)型

eatFood(cat);? //兩種傳參方式都可

eatFood(dog);?

Animal animal = buyAnimal();??

animal.eat();//方法返回向上轉(zhuǎn)型

}

}

向上轉(zhuǎn)型的優(yōu)點:讓代碼實現(xiàn)更簡單靈活。

向上轉(zhuǎn)型的缺陷:不能調(diào)用到子類特有的方法。

四、多態(tài)的實現(xiàn)

多態(tài)具體點就是去完成某個行為時,當(dāng)不同的對象去完成同一件事時(調(diào)用eat方法)會產(chǎn)生出不同的狀態(tài)。代碼如下:

class Animal {

????public void eat(){

????????System.out.println( "吃飯");

????}

}

?class Cat extends Animal{

????@Override //注解

????public void eat(){

????????System.out.println("吃魚~~~");

????}

}

?class Dog extends Animal {

????@Override

????public void eat(){

????????System.out.println("吃骨頭~~~");

????}

}

public class TestAnimal {

????public static void eat(Animal a){

????????a.eat(); //兩次調(diào)用該方法,但是結(jié)果卻不一樣

????}

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

????????Cat cat = new Cat();

????????Dog dog = new Dog();

????????eat(cat);

????????eat(dog);

????}

}

//輸出結(jié)果

吃魚~~~ 吃骨頭~~~

此時在上述代碼中當(dāng)父類的引用所指向的子類對象引用指向的對象不一樣時。調(diào)用重寫的方法(eat),所表現(xiàn)出來的行為是不一樣的(輸出結(jié)果不一樣),我們把它叫做多態(tài)。

五、向下轉(zhuǎn)型

將一個子類對象經(jīng)過向上轉(zhuǎn)型之后當(dāng)成父類方法使用,再無法調(diào)用子類的方法,但有時候可能需要調(diào)用子類特有的方法,此時可以實例化子類,然后調(diào)用子類方法即可。我們其實還可以將父類引用再還原為子類對象即可,即

向下轉(zhuǎn)型

。 語法格式:子類類型 對象名

= (強制轉(zhuǎn)換)父類對象名

?Dog myDog = (Dog) animal;

那么以上代碼為什么要強制類型轉(zhuǎn)換呢?向上轉(zhuǎn)型可以不用,因為是從小范圍向大范圍的轉(zhuǎn)換。(可以類比整型里面的強制轉(zhuǎn)換),我們現(xiàn)在提出一個問題:什么時候都可以向下轉(zhuǎn)型嗎? 答案是不,在Java中,向下轉(zhuǎn)型(將父類引用轉(zhuǎn)換為子類引用)一般需要先進(jìn)行向上轉(zhuǎn)型 見以下代碼

class Animal {

????void sound() {

????????System.out.println("Animal的sound");

????}

????void sun() {

????????System.out.println("Animal特有的sun");

????}

}

class Dog extends Animal {

????void sound() {

????????System.out.println("Dog的sound");

????}

????void fetch() {

????????System.out.println("Dog特有的fetches ");

????}

}

public class Mainn {

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

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

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

????????myDog.sound(); // 輸出: Dog barks,調(diào)用子類的覆蓋方法

????????myDog.fetch(); // 輸出: Dog fetches a ball,調(diào)用子類特有的方法

????????myDog.sound(); // 輸出: Dog barks,調(diào)用子類的覆蓋方法

????}

}

如果上面的代碼沒有?Animal animal = new Dog();,向下轉(zhuǎn)型將報錯,同時注意必須確保父類引用所指向的對象確實是子類的實例。如果父類引用所指向的對象不是子類的實例,那么即使進(jìn)行了向上轉(zhuǎn)型,向下轉(zhuǎn)型也是不安全的:見以下代碼

class Parent {} class Child extends Parent {} class AnotherChild extends Parent {}

public class Main { public static void main(String[] args) { Parent parent = new AnotherChild(); // 向上轉(zhuǎn)型 ?// 這里如果嘗試向下轉(zhuǎn)型為Child,編譯器將會報錯 ?// Child child = (Child) parent;//不安全的向下轉(zhuǎn)型 } }

//為了演示方便,這個代碼是不完整的

因此,向下轉(zhuǎn)型之前,你需要確保父類引用所指向的對象確實是你要轉(zhuǎn)型的子類的實例。這通常通過instanceof操作符來檢查:用來判斷parent是否為Child的實例,若是,返回true,否則返回false

if (parent instanceof Child) { ? ? Child child = (Child) parent; // 安全的向下轉(zhuǎn)型} else { ? ?......? ? ? ? ? ? ? ? ? ? ? ? ?// 不能轉(zhuǎn)換為Child }

我們最后思考一個問題:向上轉(zhuǎn)型的缺陷是不能調(diào)用到子類特有的方法,那么向下轉(zhuǎn)型可以調(diào)用父類特有的方法嗎?是可以的,同時向下轉(zhuǎn)型后不會影響向上轉(zhuǎn)型的操作。見以下代碼

class Animal {

????void sound() {

????????System.out.println("Animal的sound");

????}

????void sun() {

????????System.out.println("Animal特有的sun");

????}

}

class Dog extends Animal {

????void sound() {

????????System.out.println("Dog的sound");

????}

????void fetch() {

????????System.out.println("Dog特有的fetches ");

????}

}

public class Mainn {

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

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

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

????????myDog.sound(); // 輸出: Dog barks,調(diào)用子類的覆蓋方法

????????myDog.fetch(); // 輸出: Dog fetches a ball,調(diào)用子類特有的方法

????

????????myDog.sound(); // 輸出: Dog barks,調(diào)用子類的覆蓋方法

????????myDog.sun(); ??//觀察到向下轉(zhuǎn)型過程中可以調(diào)用父類的特有的方法

????????animal.sun();? ?//觀察到向下轉(zhuǎn)型后不會影響向上轉(zhuǎn)型的操作

????????animal.sound();

????}

}

//輸出結(jié)果

Dog的sound Dog特有的fetches? Dog的sound Animal特有的sun Animal特有的sun Dog的sound

六、多態(tài)的優(yōu)缺點

如我們現(xiàn)在需要打印的不是一個形狀了

,

而是多個形狀

.

如果不基于多態(tài)

,

實現(xiàn)代碼如下

class Shape {

????//屬性....

????public void draw() {

????????System.out.println("畫圖形!");

????}

}

class Rect extends Shape{

????@Override

????public void draw() {

????????System.out.println("?");

????}

}

class Cycle extends Shape{

????@Override

????public void draw() {

????????System.out.println("●");

????}

}

class Flower extends Shape{

????@Override

????public void draw() {

????????System.out.println("?");

????}

}

public class Mainn {

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

????????????Rect rect = new Rect();

????????????Cycle cycle = new Cycle();

????????????Flower flower = new Flower();

????????????String[] shapes = {"cycle", "rect", "cycle", "rect", "flower"};

????????????for (String shape : shapes) {

????????????????if (shape.equals("cycle")) {

????????????????????cycle.draw();

????????????????} else if (shape.equals("rect")) {

????????????????????rect.draw();

????????????????} else if (shape.equals("flower")) {

????????????????????flower.draw();

????????????}

????????}

????}

}

以上代碼使用了大量的 if - else,增加了代碼的

"

圈復(fù)雜度",

什么叫

"

圈復(fù)雜度

" ?

圈復(fù)雜度是一種描述一段代碼復(fù)雜程度的方式

.

一段代碼如果平鋪直敘

,

那么就比較簡單容易理解

.

而如

果有很多的條件分支或者循環(huán)語句

,

就認(rèn)為理解起來更復(fù)雜

.

因此我們可以簡單粗暴的計算一段代碼中條件語句和循環(huán)語句出現(xiàn)的個數(shù)

,

這個個數(shù)就稱為

"

圈復(fù)雜度

".

如果一個方法的圈復(fù)雜度太高

,

就需要考慮重構(gòu)

.

不同公司對于代碼的圈復(fù)雜度的規(guī)范不一樣

.

一般不會超過

10

如果使用使用多態(tài)

,

則不必寫這么多的

if - else

分支語句

,

代碼更簡單

class Shape {

????//屬性....

????public void draw() {

????????System.out.println("畫圖形!");

????}

}

class Rect extends Shape{

????@Override

????public void draw() {

????????System.out.println("?");

????}

}

class Cycle extends Shape{

????@Override

????public void draw() {

????????System.out.println("●");

????}

}

class Flower extends Shape{

????@Override

????public void draw() {

????????System.out.println("?");

????}

}

public class Mainn {

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

????????????Shape[] shapes = {new Cycle(), new Rect(), new Cycle(),

????????????????????new Rect(), new Flower()};

????????????for (Shape shape : shapes) {

????????????????shape.draw();

????????????}

????????}

????????????}

如果要新增一種新的形狀

,

使用多態(tài)的方式代碼改動成本也比較低

.見以下代碼

//公共部分

class Triangle extends Sjx?{

@Override

public void draw() {

System.out.println("△");

}

}

//If lese 改動方式

Sjx sjx=new Sjx();

????????????String[] shapes = {"cycle", "rect", "cycle", "rect", "flower", "sjx"};

????????????for (String shape : shapes) {

????????????????if (shape.equals("cycle")) {

????????????????????cycle.draw();

????????????????} else if (shape.equals("rect")) {

????????????????????rect.draw();

????????????????} else if (shape.equals("flower")) {

????????????????????flower.draw();

????????????????}else if(shape.equals("sjx"){

????????????????????????sjx.draw();

????????????????????}

????????????}

????????}

}

//多態(tài)改動方式

public class Mainn {

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

????????Shape[] shapes = {new Cycle(), new Rect(), new Cycle(),

????????????????new Rect(), new Flower(),new Sjx()};

????????for (Shape shape : shapes) {

????????????shape.draw();

????????????????????}

????????????}

????????}

對于類的調(diào)用者來說

(drawShapes

方法

),

只要創(chuàng)建一個新類的實例就可以了

,

改動成本很低

.

而對于不用多態(tài)的情況

,

就要把

drawShapes

中的

if - else

進(jìn)行一定的修改

,

改動成本更高

.

多態(tài)缺陷:

1.

屬性沒有多態(tài)性

當(dāng)父類和子類都有同名屬性的時候,通過父類引用,只能引用父類自己的成員屬性

2.

構(gòu)造方法沒有多態(tài)性

見如下代碼

~

七、避免在構(gòu)造方法中調(diào)用重寫的方法

class

B

{

public

B

() {

// do nothing

func

();

}

public

void

func

() {

System

.

out

.

println

(

"B.func()"

);

}

}

class

D

extends

B

{

private

int

num

=

1

;

@Override

public

void

func

() {

System

.

out

.

println

(

"D.func() "

+

num

);

}

}

public class

Test

{

public static

void

main

(

String

[]

args

) {

D d

=

new

D

();

}

}

//

執(zhí)行結(jié)果

D

.

func

()

0 //

此時子類對象還沒構(gòu)造完成,故num的值為0

結(jié)論:盡量不要在構(gòu)造器中調(diào)用方法

(

如果這個方法被子類重寫

,

就會觸發(fā)動態(tài)綁定,

但是此時子類對象還沒構(gòu)造完成

),

可能會出現(xiàn)一些隱藏的但是又極難發(fā)現(xiàn)的問題

.

柚子快報激活碼778899分享:開發(fā)語言 Java之多態(tài)

http://yzkb.51969.com/

參考閱讀

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/18834593.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機訪問

文章目錄