类与接口(五)java多态、方法重写、隐藏
一、Java多態(tài)性
面向?qū)ο蟮娜筇匦?#xff1a;封裝、繼承、多態(tài)。
多態(tài)的類型,分為以下兩種:
- 編譯時(shí)多態(tài): 指的是 方法重載。編譯時(shí)多態(tài)是在編譯時(shí)確定調(diào)用處選擇那個(gè)重載方法,所以也叫 靜態(tài)多態(tài),算不上真正的多態(tài)。所以,一般說的多態(tài)都是運(yùn)行時(shí)的多態(tài)。
- 運(yùn)行時(shí)多態(tài): 由于 方法重寫,所以想要確定引用變量所調(diào)用的方法的入口,必須根據(jù)運(yùn)行時(shí)的引用變量所指向的實(shí)例對象來確定。從而使得同一個(gè)引用變量調(diào)用同一個(gè)方法,但不同的實(shí)例對象表現(xiàn)出不同的行為。再簡單點(diǎn)來說,就是在運(yùn)行時(shí),可以通過指向基類的指針,來調(diào)用實(shí)現(xiàn)子類中的方法。
下面講的多態(tài)都是指 運(yùn)行時(shí)的多態(tài)。
多態(tài)的定義: 指允許不同類的對象對同一消息做出不同的響應(yīng)。即同一消息可以根據(jù)發(fā)送對象的不同而采用多種不同的行為方式。(發(fā)送消息就是函數(shù)調(diào)用);
上面的定義參考了網(wǎng)上的說法,定義中的不同類,都是由同一個(gè)基類擴(kuò)展而來。
多態(tài)的好處:
- 可替換性(substitutability)。多態(tài)對已存在代碼具有可替換性。例如,draw函數(shù)對圓Circle類工作,對其他任何圓形幾何體,如圓環(huán),也同樣工作。
- 可擴(kuò)充性(extensibility)。多態(tài)對代碼具有可擴(kuò)充性。增加新的子類不影響已存在類的多態(tài)性、繼承性,以及其他特性的運(yùn)行和操作。實(shí)際上新加子類更容易獲得多態(tài)功能。例如,在實(shí)現(xiàn)了圓錐、半圓錐以及半球體的多態(tài)基礎(chǔ)上,很容易增添球體類的多態(tài)性。
- 接口性(interface-ability)。多態(tài)是超類通過方法簽名,向子類提供了一個(gè)共同接口,由子類來完善或者覆蓋它而實(shí)現(xiàn)的。如圖8.3 所示。圖中超類Shape規(guī)定了兩個(gè)實(shí)現(xiàn)多態(tài)的接口方法,computeArea()以及computeVolume()。子類,如Circle和Sphere為了實(shí)現(xiàn)多態(tài),完善或者覆蓋這兩個(gè)接口方法。
- 靈活性(flexibility)。它在應(yīng)用中體現(xiàn)了靈活多樣的操作,提高了使用效率。
- 簡化性(simplicity)。多態(tài)簡化對應(yīng)用軟件的代碼編寫和修改過程,尤其在處理大量對象的運(yùn)算和操作時(shí),這個(gè)特點(diǎn)尤為突出和重要。
java的多態(tài)性三要素:
- 繼承;
- 重寫;
- 父類的引用指向子類的引用
多態(tài)性的實(shí)現(xiàn): 依靠動(dòng)態(tài)綁定;
綁定: 將一個(gè)方法調(diào)用與方法主體關(guān)聯(lián)起來。
前期綁定: 在程序執(zhí)行前綁定,由編譯器和鏈接程序完成,C語言的函數(shù)調(diào)用便是前期綁定。
動(dòng)態(tài)綁定: 也稱 后期綁定。在運(yùn)行時(shí),根據(jù)具體的對象類型進(jìn)行方法調(diào)用綁定。除了static方法、final方法(private方法也是final方法),其他方法都是動(dòng)態(tài)綁定;
二、方法重寫 與 隱藏
方法重寫: 就是子類中覆蓋了從父類繼承下來的方法(不是所有的父類方法都可以覆蓋),從而使得通過父類的引用來調(diào)用重寫后的方法。也就是說,父類類型與子類類型只保留重寫后的方法。
隱藏: 覆蓋是相對重寫而言的。當(dāng)子類中出現(xiàn)與父類相同的方法時(shí),重寫是子類與父類只保持一份,但方法隱藏則是子類與父類各自獨(dú)立保持一份,也就兩份。從父類繼承下來的成員中,除了部分方法是可以重寫外,其余成員都是隱藏,如變量、內(nèi)部類、靜態(tài)方法等。
注意: final方法既不能重寫,也不能隱藏。
class ParentClass{public int a = 5;protected final String name = "parentClass";public final void finalMethod() {//final方法,子類既不能重寫,也不能隱藏System.out.println("final方法");}public static void monday() {//靜態(tài)方法System.out.println("父類ParentClass的monday()方法");}public void count() {//可繼承的成員方法System.out.println("父類ParentClass的count()方法");}class InnerClass{//內(nèi)部類public InnerClass() {System.out.println("父類ParentClass的內(nèi)部類");}} }class ChildClass extends ParentClass{public int a = 5;protected final String name = "ChildClass";/*//編譯不通過* public final void finalMethod() {System.out.println("final方法");}*/public static void monday() {//靜態(tài)方法System.out.println("子類ChildClass的monday()方法");}public void count() {//可繼承的成員方法System.out.println("子類ChildClass的count()方法");}class InnerClass{//內(nèi)部類public InnerClass() {System.out.println("子類ChildClass的內(nèi)部類");}} }public class MyTest {public static void main(String[] args) {ChildClass child = new ChildClass2();ParentClass parent = child; //類型上轉(zhuǎn)System.out.println("---------------變量的隱藏測試-----------------");child.a = 10;System.out.println("parent.a: "+parent.a);System.out.println("child.a: "+child.a);System.out.println("\n---------------靜態(tài)方法的隱藏測試-----------------");parent.monday();child.monday();System.out.println("\n---------------方法的重寫測試-----------------");parent.count();child.count();System.out.println("\n---------------內(nèi)部類的隱藏測試-----------------");ParentClass.InnerClass pa = parent.new InnerClass();ChildClass.InnerClass ch = child.new InnerClass();} }—————變量的隱藏測試—————–
parent.a: 5
child.a: 10
—————靜態(tài)方法的隱藏測試—————–
父類ParentClass的monday()方法
子類ChildClass的monday()方法
—————方法的重寫測試—————–
子類ChildClass的count()方法
子類ChildClass的count()方法
————–內(nèi)部類的隱藏測試—————–
父類ParentClass的內(nèi)部類
子類ChildClass的內(nèi)部類
??上面的例子中,只有count()方法是被重寫了,父類類型與子類類型只保持重寫后的方法,而其他成員都是隱藏,父類類型保持一份,子類類型也保持一份。
方法重寫的條件
- 重寫的方法是子類從父類繼承下來的實(shí)例方法,不能是靜態(tài)方法
- 子類重寫后的方法的 返回類型 必須是 原父類方法的返回類型的可替換類型
- 子類重寫后的方法的訪問權(quán)限 不能比 原父類方法的訪問權(quán)限低;
- 子類重寫后的方不能比父類方法拋出更多的異常;
- 當(dāng)重寫泛型方法時(shí),先進(jìn)行類型擦除。再按照上面的4個(gè)小點(diǎn),重寫類型擦除后的方法;
可替換類型補(bǔ)充:
- 對于返回類型是基本類型、void,重寫方法的返回類型必須是一樣;
- 對于返回類型是引用類型,返回類型可替換成該類型的 子類型;
??解析一下此例子中的泛型方法重寫,父類中的泛型方法getValue()進(jìn)行類型擦除后,是:
ParentClass getValue(ParentClass t){return null; }所以,子類ChildClass的方法重寫是合理的。
作者:jinggod
出處:http://www.cnblogs.com/jinggod/p/8503153.html
總結(jié)
以上是生活随笔為你收集整理的类与接口(五)java多态、方法重写、隐藏的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 类与接口(四)方法重载解析
- 下一篇: java面试题大合集(开发者必看三)