物件導向的基本特徵之多型

2021-09-11 21:37:31 字數 2700 閱讀 6348

本文參考

public class a 

public string show(a obj)

}public class b extends a

public string show(a obj)

}public class c extends b

public class d extends b

public class test

}

執行結果:

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、2、3還好理解,從4開始就開始糊塗了,對於4來說為什麼輸出不是「b and b」呢?

首先我們先看一句話:當超類物件引用變數引用子類物件時,被引用物件的型別而不是引用變數的型別決定了呼叫誰的成員方法,但是這個被呼叫的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法。這句話對多型進行了乙個概括。其實在繼承鏈中物件方法的呼叫存在乙個優先順序:this.show(o)、super.show(o)、this.show((super)o)、super.show((super)o)。

分析:從上面的程式中我們可以看出a、b、c、d存在如下關係。

首先我們分析5,a2.show(c),a2是a型別的引用變數,所以this就代表了a,a2.show(c),它在a類中找發現沒有找到,於是到a的超類中找(super),由於a沒有超類(object除外),所以跳到第**,也就是this.show((super)o),c的超類有b、a,所以(super)o為b、a,this同樣是a,這裡在a中找到了show(a obj),同時由於a2是b類的乙個引用且b類重寫了show(a obj),因此最終會呼叫子類b類的show(a obj)方法,結果也就是b and a。

按照同樣的方法我也可以確認其他的答案。

方法已經找到了但是我們這裡還是存在一點疑問,我們還是來看這句話:當超類物件引用變數引用子類物件時,被引用物件的型別而不是引用變數的型別決定了呼叫誰的成員方法,但是這個被呼叫的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法。這我們用乙個例子來說明這句話所代表的含義:a2.show(b);

這裡a2是引用變數,為a型別,它引用的是b物件,因此按照上面那句話的意思是說有b來決定呼叫誰的方法,所以a2.show(b)應該要呼叫b中的show(b obj),產生的結果應該是「b and b」,但是為什麼會與前面的執行結果產生差異呢?這裡我們忽略了後面那句話「但是這兒被呼叫的方法必須是在超類中定義過的」,那麼show(b obj)在a類中存在嗎?根本就不存在!所以這句話在這裡不適用?那麼難道是這句話錯誤了?非也!其實這句話還隱含這這句話:它仍然要按照繼承鏈中呼叫方法的優先順序來確認。所以它才會在a類中找到show(a obj),同時由於b重寫了該方法所以才會呼叫b類中的方法,否則就會呼叫a類中的方法。

所以多型機制遵循的原則概括為:當超類物件引用變數引用子類物件時,被引用物件的型別而不是引用變數的型別決定了呼叫誰的成員方法,但是這個被呼叫的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法,但是它仍然要根據繼承鏈中方法呼叫的優先順序來確認方法,該優先順序為:this.show(o)、super.show(o)、this.show((super)o)、super.show((super)o)。

參考資料:

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));

system.out.println("5--" + a2.show(c));---a2.show(c),a2是a型別的引用變數,所以this就代表了a,a2.show(c),它在a類中找發現沒有找到,於是到a的超類中找(super),由於a沒有超類(object除外),所以跳到第**,也就是this.show((super)o),c的超類有b、a,所以(super)o為b、a,this同樣是a,這裡在a中找到了show(a obj),同時由於a2是b類的乙個引用且b類重寫了show(a obj),因此最終會呼叫子類b類的show(a obj)方法,結果也就是b and a。這種情況弄懂後面的都很好處理了。

更加詳細步驟請到參考文章處檢視:,我只是記下筆記。

物件導向基本特徵

通過學習設計模式對物件導向程式設計有了更深層次的了解。在 大話設計模式 一書中的第乙個設計模式裡 簡單工廠模式 體會到了自己學習物件導向程式設計時的歷程。首先要保證 無錯,我想這是大部分初學者的心願。其次就是 規範,這一點是很重要的,程式不僅僅是寫給自己看的,更需要讓別人能看懂。別人能看懂還不行,畢...

物件導向基本特徵

物件導向4大基本特徵 抽象 封裝 繼承 多型。抽象。將一些事物的共性抽離出來歸為乙個類。如對於動物,具有生命體徵 活動能力等區別於其它事物的共同特徵 封裝。有選擇地隱藏和暴露資料和方法。比如有u盤這個類,我希望隱藏內部組成和實現,只暴露usb介面以供使用 繼承。子類可以直接使用父類的部分資料和方法,...

物件導向的三個基本特徵 物件導向基本特徵

物件導向的三個基本特徵 封裝是物件和類概念的主要特徵,就是把客觀的封裝起來,只對外暴露出來,並把自己的資料和方法只讓可信的類或物件操作作用 隱藏實現細節,使得 模組化 使用現有類的所有功能,並且無需重新編寫原來的類中的方法對這些功能的擴充套件,oc只能實現單繼承,如果想要實現多繼承的話可以通過分類或...