我們都知道面向對象有四個基本特性:抽象、封裝、繼承、多態。這四個特性,概括起來可以這么理解,抽象、封裝、繼承是多態的基礎,多態是抽象、封裝、繼承的表現。多態,是Java中非常重要的一個部分,所以今天來談一下多態(Polymorphism)。
什么是多態
不同類的對象對同一消息作出不同的響應就叫做多態。就像上課鈴響了,上體育課的學生跑到操場上站好,上語文課的學生在教室里坐好一樣。
多態的作用
簡單講就是解耦。再詳細點講就是,多態是設計模式的基礎,不能說所有的設計模式都使用到了多態,但是23種中的很大一部分,都是基於多態的。
多態存在的三個條件
1、有繼承關系
2、子類重寫父類方法
3、父類引用指向子類對象
補充一下第二點,既然多態存在必須要有“子類重寫父類方法”這一條件,那么以下三種類型的方法是沒有辦法表現出多態特性的(因為不能被重寫):
1、static方法,因為被static修飾的方法是屬於類的,而不是屬於實例的
2、final方法,因為被final修飾的方法無法被子類重寫
3、private方法和protected方法,前者是因為被private修飾的方法對子類不可見,后者是因為盡管被protected修飾的方法可以被子類見到,也可以被子類重寫,但是它是無法被外部所引用的,一個不能被外部引用的方法,怎么能談多態呢
多態的分類
1、編譯時多態,即方法的重載,從JVM的角度來講,這是一種靜態分派(static dispatch)
2、運行時多態,即方法的重寫,從JVM的角度來講,這是一種動態分派(dynamic dispatch)
關於這一點,在寫到JVM的時候會詳細講到
分析多態問題的幾條原則
如果不去理解多態的原理,就從使用的角度來講,以個人的學習、工作這幾年的經驗,總結出了多態無非就是三句話:
比如我們有一個父類Father,有一個子類Children
1、向上轉型是自動的。即Father f = new Children()是自動的,不需要強轉
2、向下轉型要強轉。即Children c = new Father()是無法編譯通過的,必須要Children c = (Children)new Father(),讓父類知道它要轉成具體哪個子類
3、父類引用指向子類對象,子類重寫了父類的方法,調用父類的方法,實際調用的是子類重寫了的父類的該方法。即Father f = new Children(),f.toString()實際上調用的是Children中的toString()方法