我們知道子類物件可以賦給父類物件,也可以說子類物件可以完全替換父類物件並出現在父類物件可以出現的任何地方,且程式的行為不會發生改變,但反過來父類物件是不能替換子類物件的!比如汽車類物件就不能替換卡車類物件(雖然卡車也是汽車),因為汽車包含的範圍比卡車要大,它也可以是私家車!
這種特性就被稱為「黎克特制替換原則(liskor substiution principle)」。
黎克特制替換原則是軟體設計應該遵守的重要原則之一,有了黎克特制替換原則,才使繼承復用成為可能,只有當子類可以替換掉父類時軟體功能不受影響,父類才能真正被復用,而子類也能在父類的基礎上增加新的行為。
is用於檢查物件和指定型別是否相容。例如要判斷員工集合中的乙個元素是否是se物件,就可以使用下面一段**
if (empls[i] isse)
as主要用於兩個物件之間的型別轉換。如下所示
se se=empls[1] as se;
而且使用as操作符進行型別轉化失敗時會返回null,而不會報異常!
但是這並不代表不需要異常處理
pm pm=empls[1] as pm;
pm.sayhi();
如果empls轉換為pm失敗,雖然這一句沒有異常,但是下一句sayhi()方法就可能會報錯了!
在黎克特制替換原則中指出子類物件可以代替父類物件,那麼在開發程式時我們可以編寫以父類型別作為形式引數的方法,在實際呼叫時傳入子類物件,從而實現多型。
程式在執行中自動判斷實際引數屬於那種子類,呼叫相應子類的方法,從而完成多型。
小結:用虛方法實現多型的基本步驟
子類重寫父類的虛方法,其中有兩種方式
建立父類物件,用子類物件示例化這個父類物件
以父類型別作為形式引數,它的子類物件作為實際傳入
執行時,根據實際建立物件的型別決定執行那個方法。
demo:
publicclass
traffictool
}
從這個demo中我們不難看出:如果我們例項化乙個traffictool物件去呼叫它的run()方法,實際意義不大,因為交通工具本身是乙個巨集觀的、抽象的概念,不是某乙個具體的交通工具。假如我們不希望這個父類被例項化,並且只提供方法的定義,自己不去實現,而讓子類實現這些方法,可以使用抽象類和抽象方法來解決!
抽象方法是乙個沒有實現的方法,通過在定義是增加abstract關鍵字可以宣告抽象方法,其語法如下:
訪問修飾符 abstract 返回值型別 方法名();
注意抽象方法沒有閉合的{}括號,而是直接跟了乙個;分號,也就是說抽象方法不能有方法體。
含有抽象方法的類必然是抽象類,同樣我們用abstract關鍵字來定義抽象類,其語法如下:
訪問修飾符 abstract class 類名{}
當從乙個抽象父類派生乙個子類時,子類將繼承父類的所有特徵,包括它未實現的抽象方法,抽象方法必須在其子類中實現,除非它的子類也是乙個抽象類。與子類重寫父類的虛方法一樣,在子類中也可以使用override關鍵字來重寫父類的抽象方法。其語法如下:
訪問修飾符 override 返回值型別 方法名()
虛方法和抽象方法的區別
虛方法抽象方法
用virtual修飾
用abstract修飾
要有方法體即使是乙個;號
不允許有方法體
可以被子類override
必須被子類override
除了密封類外定義
只能在抽象類中定義
深入理解多型
能將每個函式都申明為虛函式,但是會影響效率,不建議這樣做,虛函式指標呼叫重寫函式是在程式執行時候進行的,因此需要一些定址操作才能真正呼叫函式,如果都設定成虛函式,效率會低很多 多型的實現效果 呼叫同樣的語句能表現不同的表現形式 多型實現的三個條件 有繼承,有虛函式重寫,有父類指標指向子類物件 多型的...
深入理解多型
1 黎克特制替換 概述 在子類物件中可以替換所有使用的父類物件 原則 父類物件是不能替換子類物件的 應用 使繼承復用成為可能,當子類可以替換父類時,軟體功能不受影響,父類才能真正被復用,而子類也能夠在父類的基礎上增加新的行為 關鍵字 is和a操作符 2 is和as操作符的使用 is操作符用於檢查物件...
深入理解Java多型機制
目錄 1,多型的概念?2,存在的條件?3,案列解析?4,應用場景?1,多型的概念 父類引用指向子類物件,通俗點就是,在編譯時不繫結是什麼方法,根據你傳進來的值,是什麼就會執行什麼。2.存在條件 第一,要有繼承 第二,要有方法的重寫 第三,父類引用指向子類物件 3,案列解析 好好體會以下這個案例,通過...