1. 程式人生 > >關於繼承中,方法的重寫和過載(摘抄)

關於繼承中,方法的重寫和過載(摘抄)

首先需要明白什麼是繼承?為什麼需要繼承?繼承的是什麼?

軟體工程裡面,有個很重要的事情,就是“程式碼複用”,將需要重複使用的程式碼抽取出來,封裝成函式,便是最簡單的複用。此處還沒有繼承的概念,當OOP的思想出來後,出現了“類”——資料與行為的封裝體。在類裡面,資料被稱之為屬性(Attribute);而行為則被稱之為函式(Funcation)或者方法(Method)。複用也就是複用這些個東西。什麼情況下需要複用呢?當我們的程式碼有一部分功能已經完成,而我們對其功能感覺還不足以滿足我們的需求,那麼便要對其改造。當然,我們不能直接修改已經完成的程式碼,只能退而求其次,將他的程式碼複製過來,然後把不滿意的地方進行修改!這樣短暫的滿足了要求,但是問題又來了,原來的類升級了,部分功能更新了。我拿來一瞧,倘若改的是我們拿來之後改過的部分,那倒沒什麼問題,反正我們還是要改的。但如果改的是其他我們需要的功能,那麼,我們必須再次拿出程式碼來複制一遍。這樣的做法,談不上覆用。那麼如何才能複用呢?繼承

繼承什麼,繼承一個類。類裡面有什麼,我們就可以繼承什麼。屬性、方法都可以被繼承

首先繼承過後的類跟原來的類不是一個類,他們之間的關係很簡單,新的類知道自己擴充套件的是誰,而反過來不行。例如A extends B,B是不知道被A繼承了的,只有通過A類去反推才能得知。A可以看做是B的另外一個版本。B不具備或者不滿足的功能,在A裡面重新做一下。這裡有一個問題需要講一下,類裡面包含了物件的資訊,而物件在記憶體裡面,僅僅包含了資料,而沒有方法,所有的方法都在類裡面,當我們對某個物件的引用呼叫其方法時,等於將記憶體中,該物件的資料交給其方法去處理,那麼此時就有個方法定位的問題。很明顯,呼叫方法時就已經指明瞭呼叫這個方法的物件,那麼從該物件的類開始搜尋,如果搜到該方法,則呼叫之,若搜尋不到,則向上搜尋其超類,以此類推,直到搜到為止。如果自身存在和超類中一致的方法,根據自身優先原則,自身的方法將被呼叫,那麼超類中的方法很自然就被遮蓋了。注意此處的用詞,為遮蓋而不是替換,超類中的方法依然存在,只不過不會被呼叫而已。

這個現象即被稱之為方法覆蓋,又稱之為重寫(Override)。想要呼叫父類的方法,在方法內使用super關鍵字顯性呼叫即可!

當我們的類不希望被繼承(擴充套件),也即,設定某個類為最終版本,不允許有某個類對其進行繼承,那麼該類應當被修飾為final,當你嘗試去繼承一個final類時,會發生編譯錯誤。而有些時候,我們並不完全限定死我們的類不被繼承,而僅僅是限定某些方法不被重寫(因為子類是可以冒充超類的),那麼我們就需要將對應的方法修飾為final,也即,此方法為最終版本,不允許修改!重寫一個final方法會引發編譯錯誤。

那麼此時有個額外的問題,子類能夠過載(Overload)超類的final方法?

答案是可以!

無論是過載自身還是超類的方法,過載的方法之間,除了方法名一致外,還有其他聯絡麼?很明顯,方法簽名最重要的部分是方法名和引數型別列表!而過載即為同名不同參,也即是說,過載的方法之間,除了方法名很湊巧的一致外,本質上根本就完全是兩個不同的方法,毫無關係而言

但重寫不行,因為方法簽名一致或者說是相容吧,那麼如何相容法呢?

一個方法的申明,有以下元素組成:修飾符,返回值型別,方法名,引數列表,異常型別集合

子類跟超類某方法的簽名完全一致當然是最好,這個絕對沒問題。

那麼是不是必須一致呢,必須一致的只有方法名和引數列表而已,其他的因情況而異

異常集合,當然跟引數列表不一樣,是無序的,你可以寫多個。但是有一個原則,你所有的異常範圍不能超越超類裡面該方法所申明的異常範圍。否則的話,就是掛羊頭賣狗肉,編譯不會通過。

修飾符也一樣,訪問性不能更狹隘,可以平級,但是絕對不能將public的方法寫成private,理由同上!