《HeadFirstJava》是最通俗易懂也是最適合小白入門的JAVA書。segmentfault
好久好久之前,我在學習《HeadFirstJAVA》時,嘗試着把本身理解的內容寫成文章,因而就有了《一個小白眼中的「面向對象」》,如今,書已經完全讀完了,因此要再寫一些本身的體會。學習
在軟件開發中,有這樣一個規律:spa
咱們能夠從這個角度,來看一看對象、類、接口、繼承之間的關係。3d
咱們已經知道,類是對象的模板,對象是類的克隆。
當咱們須要建立一系列相同的對象時,就把它們共有的部分抽象出來,所以就有了類。
對象
(一)blog
開始以前,咱們先想想,全部的動物都有吃飯這個方法eat(),若是每種動物都單獨寫一個eat()方法,那就是許許多多相同的代碼。繼承
既然又出現了相同的代碼,咱們可不能夠把它們抽象出來呢?可不能夠寫一個通用的類,包含了這些共同的方法,而全部具體的類都「克隆」這個通用的方法呢?
固然能夠,因而就有了下圖:接口
這就是繼承,被繼承的類稱爲父類,執行繼承的類叫作子類,繼承的做用在於,子類擁有了父類的全部屬性和方法。圖片
對於初學者來講聽到這個詞,可能會想到現實中的財產繼承,但計算機的繼承和這個並不同,若是用一個更貼切的詞語來形容計算機的「繼承」,那應該是生物學中的「遺傳」。開發
爲何說計算機的繼承有點像「遺傳」呢,由於並非子類繼承以後,父類就沒有了,而是把父類完整的複製一份,不管發生多少次繼承,父類都仍是那個父類,一點也沒有減小。
(二)
雖然全部的動物都會吃,但並非全部動物都會飛,若是想給鳥類添加fly()的方法,能夠嗎?
固然能夠。
(三)
若是全部陸生動物都會走路,但並非全部的動物走路姿式都同樣,那麼可不能夠只給幾種特殊的動物定義單獨的wolk(),而其餘的動物使用父類的work()呢?
固然能夠。
所以又引出一個結論:
當對象被調用了一個方法,程序會先從對象所屬的類中尋找此方法,若是沒有,再去此類的父類中尋找,若是尚未,就一直向上尋找,直到找到最頂層的父類,若是尚未,就會報錯。
(四)
咱們繼續第三個問題,全部的動物都有鳴叫的方法call(),可是全部的動物叫聲都不同,那麼若是new一個Animal對象,它會怎麼叫呢?
答案是:根本就不存在Animal這種對象,所以,有些類是不能new的。這種對象一旦new出來,不只沒有意義,並且很危險。
因此,必需要對這種特殊的類,作一個標註,使它不能new,但能夠被繼承。
這樣,就有了抽象類,抽象類中至少有一個抽象方法。
抽象的,就是不具體的,這意味着只須要關注抽象方法的功能,而不關心它的具體實現方式。抽象方法只有方法名、返回值類型,而沒有語句,因此它不能被執行。
抽象類只有被具體類繼承,而且經過覆蓋父類的方法,把抽象方法實現以後,才能被new出來。
由於上圖中的Bird,覆蓋了Animal的Call(),它不包括任何抽象方法,因此Bird是一個具體的類,能夠被new出來。
(五)
人類是哺乳類動物也是靈長類動物,那麼能夠同時繼承兩個類嗎?
在回答問題以前,先來看一個例子:
播放器按照功能能夠分爲CD、VCD、DVD,他們都有播放方法Play()。
若是有一種新型的VCD和DVD的綜合播放器,那應該怎麼繼承呢?
同時繼承兩個父類,看似這樣沒問題,但實際調用Play()的時候,到底調用哪一個父類的Play()方法呢?
因此這是不行的,事實上,Java也是不容許這樣作的。
那麼若是有這種「繼承」兩個類的需求,怎麼辦呢?
有一種方法,就是把Play()變成抽象方法,讓複合播放器實現這個抽象方法,便可。
但這樣作,只是把多重繼承變成了單一繼承,雖然可用,但沒有從根本上解決問題。
因而,接口出現了,接口的出現就能夠解決多重繼承的問題。
(六)
若是有一種寵物貓,它既有貓的屬性,也有做爲寵物的功能,按理說,它應該同時繼承於Animal和Pet這兩個類,可現實是不容許這麼作。
如何用接口實現呢?——把Pet類的全部方法都變成抽象方法!而Animal不變。
這樣,從理論上能夠避免方法的衝突。爲何呢?由於實現抽象方法必需要覆蓋,這樣,即便父類和這個抽象類有重名方法,也會被子類覆蓋掉。
但Pet畢竟仍是個類啊,Java不容許繼承兩個類。
因此,什麼是接口呢?接口就是100%抽象的類。接口只有抽象方法。
如今的Cat類依然能夠繼承Animal,但對於Pet來講,就不是繼承了,而是實現了Pet接口。
因爲接口實100%抽象的,因此永遠也不會出現方法重名了。
用一句話概況就是,一個類只能繼承另外一個類,接口只能繼承另外一個接口,但類能夠實現多個接口。
其實接口(interface)也屬於類(class),那麼他們有什麼區別呢?
類是用來New對象的,接口是用來被實現的,因此當某個類實現了某個接口以後,它就具有了這個接口的全部功能。所以才說:接口其實是一種協議、一種規範。
讓咱們回到這個規律:
由於一樣的對象出現了兩次,因此把對象的共同點抽象出來,就有了類。
由於兩個類有相同的功能,因此把相同的功能抽象出來,就有了繼承。
由於要解決繼承兩個類的問題,因此把一個類抽象出來,就有了接口。
本文的內容大可能是基於《Head First Java》精簡出來的,所以比較基礎,實際項目中,類和接口有它們特定的做用。
接口是圖紙,是上層建築,是從宏觀上規劃一個項目的構成。就像錢塘江大橋的修築,固然不能從頭開始一點一點的來搭建,而是先有圖紙,再有零件。把一個項目分紅幾個大零件,最後再拼裝起來。
類是方便量產零件的模具。當開發商拿到圖紙以後,只看圖紙造零件並非很方便,生產效率也低。因而開發商在圖紙的基礎上進行加工,使其從扁平的圖紙變成一個個活生生的模板,根據這個模板能夠直接量產零件。這樣就提升了效率。
回到計算機,實際的軟件項目就是,先定接口,接口規範了某個方法的功能,但不關心具體實現方式。
而後就能夠放心的分工了,因爲接口是肯定的,只要每一個人的代碼都遵循接口的規範,就能夠保證合做編寫的代碼能夠成功對接。
在這些接口上寫出來的類,就能夠知足項目的功能了。
因此類是量產的模具,接口除了解決多重繼承以外,也是項目的圖紙。