首頁 > 軟體

天才第一步:Java零基礎入門,就從這份阿里p7大佬分享的筆記學起

2021-05-23 09:30:30

今日分享開始啦,請大家多多指教~

繼承與多型既是類與類之間的關係,又是一種思考問題的方式。

繼承

java裡面有類這樣的概念,你可以有Person類來指代人,也可以詳細一點,用Teacher類來指代老師,也可以用childen類來指代孩子,那麼這些類與類之間是否也有一定的關係呢?

答案是有的,比如作為一個老師,他既屬於Teacher類,也屬於Person類。又比如,狗既屬於dog類,又屬於animal類。那麼我們發現針對於每一個物件來說,它都可以分屬於很多種類別。

我們又可以想一想,科學界對於動植物的劃分是可以從界門綱目科屬種依次從大到小的來逐層劃分的,因此,作為面向物件程式設計,我們也由此可以瞭解到一種如上述劃分動植物一樣的繼承的思想。

話不多說,我們用程式碼來演示,請看如下程式碼

請看上圖中,我寫了animal類,cat類,bird類三個類,我們發現無論是animal,cat還是bird,它們都有屬於自己的名字,都會吃東西,不同的是隻有bird會飛。我們發現關於名字和吃的程式碼在三個類裡面都是一樣的,那麼這是不是就造成了程式碼的冗餘呢?

另外再思考一個問題,無論是什麼動物,只要它是動物,它就一定會吃以及一定有名字,但不一定會游泳或者飛。因此我們是不是可以把animal設為一個父類,把cat和bird設為子類,將關於吃和名字的程式碼設定在animal裡面,再讓cat和bird繼承animal,這樣就能解決程式碼冗餘的問題呢?

答案是可以的,具體請看如下程式碼

簡化後的程式碼我們看到所有的有關名字和吃的程式碼我都放到animal裡面,然後要記住一點是java裡面使用extends來申明子父類的關係

比如 A extends B 那麼,A就是B的子類,B就是A的父類,它們的關係是 is-a 的關係,比如Teacher extends Person,就代表了老師是一個(is a)人,又比如dog extends animal 就代表了狗是一個(is a)動物。這就是java裡面的繼承。

(注:父類,又稱超類,基類。子類,又稱派生類)

下面來說說繼承的幾點性質

1.我們發現其實繼承關係裡面,父類所含有的屬性只是子類的一部分,子類對父類的功能進行了擴展和延伸。

2.java裡面只支援單繼承,也就是一個子類只能有一個父類。(C++/Python等語言裡面支援多繼承)

3.對於父類裡面private的欄位和方法,子類繼承了,但是無法訪問。

4.在子類的例項中也包含著父類的例項,通過使用super關鍵字來得到父類例項的引用。

多型

何為多型,就是多種狀態嘛,結合我們的上文,我們可以知道如果一個男老師可以繼承Teacher的屬性又繼承husband的屬性,那麼我們什麼時候需要這個男老師來表現出老師的屬性,以及什麼時候需要來表現出丈夫的屬性呢?

答案是如果這個男老師在學校裡面,那麼他就要表現出老師的屬性,如果這個男老師工作結束回家了以後,他就要表現出丈夫的屬性。這就是多型。首先要明確一點,多型是基於繼承來實現的。

要想從程式碼上面來實現多型,我們就必須先了解向上轉型、動態繫結

向上轉型

向上轉型,顧名思義,就是往上轉嘛。具體操作就是將一個子類物件用一個父類引用去接收。

具體例項如下

如上圖程式碼所示,這就是向上轉型。向上轉型可以發生在直接賦值(如上),方法傳參,方法返回三種情況,下面再用程式碼來演示方法傳參和方法返回兩種情況。

動態繫結

動態繫結是向上轉型的一個效果。如下圖程式碼

我在子類B中寫了一個返回類型,方法名稱,傳入參數與父類A中完全一致的eat方法,然後訪問向上轉型為類型A的變數b1的eat方法,按理來說,我將 b1 向上轉型為 類型A ,那麼我調 eat 方法應該也是調A中的 eat 方法,但其實最終程式運行的結果是呼叫了子類B的 eat 方法,這樣就叫做動態繫結。

即呼叫向上轉型的引用裡面的方法,如果子類中也有返回類型,方法名稱,傳入參數完全一樣的方法,那麼將會呼叫子類的方法

方法重寫與方法覆蓋

方法重寫

在上面我們看到子類中有方法返回類型,方法名稱,傳入參數與父類中完全一樣,這樣的行為就叫做方法的重寫。

方法重寫要注意幾點:

1.重寫是發生在子父類中的,在同一個類裡面只支援方法過載。重寫需要保證方法名稱,傳入參數要完全一樣,返回類型要相容。

2.返回類型必須要相容,什麼意思?就是子類中返回的類型必須要和父類返回的類型具有繼承的關係或者完全和父類一致。

(這就用到了我們上面的向上轉型的知識了,要記住,java裡面子類是可以隨意轉換成父類的,也就是你可以把子類看成是和父類一樣的類,但是反過來就不行了,你不能把一個父類看成一個子類。要理解這點,就能理解java中很多地方都支援子類轉父類的操作。)

3.private,static,final修飾的父類方法無法被重寫。

4.子類的方法的訪問許可權不能低於父類的方法的訪問許可權。

5.我們可以使用註解來對重寫進行檢查。具體如下面程式碼

要注意,註解並不是註釋,如果你的重寫有錯誤,那麼註解是會報錯的。

方法過載

方法過載的規則是 方法名稱要相同,傳入參數要不同,返回類型不做要求。

方法過載既可以在同一個類中發生,也可以在子父類中發生。

過載和重寫的區別我們從字面意思就能知道,過載,說明原來的方法還在,重寫,說明原來的方法以及被覆蓋了。這也就是為什麼動態繫結的時候我們呼叫向上轉型的父類引用,調出來的卻是子類的方法,因為子類已經重寫了父類的方法,當我的物件實際上就是子類的時候,那麼它就只會呼叫子類重寫的方法。

下面給出程式碼的例子

認識多型

有了上面的知識儲備之後,我們就可以來使用多型的思想來設計一些程式。

具體一點就是我們可以寫一些只關注父類的程式碼,但其實可以由不同的子類傳入(這就是向上轉型嘛),然後呼叫對應的方法以後,會呼叫到各個子類重寫的方法(這就是動態繫結嘛),這樣就可以形成一組程式碼,多種表現形式的效果,這就是多型

下面給出一個具體的簡單例子來幫助理解

這樣我們就簡單地完成了一個多型的設計,如果能理解上述程式碼,相信你也一定對java裡面的多型有所瞭解了。

抽象類

要講抽象類,讓我們來回顧一下上篇部落格中所講的多型吧繼承與多型

我們發現,在實現這樣一個多型思想的程式碼的時候,父類Worker好像啥都沒做,主要的列印工作其實是由各個子類裡的work函數完成的,因此,我們可以對父類進行一個更詳細的描述,將父類這樣沒有發生實際作用的work函數聲明為抽象函數,那麼包含抽象函數的類就叫做抽象類。

注意:無論是抽象類還是抽象方法都是用abstract來聲明,含有抽象方法的類一定是抽象類,但是抽象類也可以不含有抽象方法。

下面給出程式碼例項

要注意兩點:

1.抽象類是不能被例項化的。

2.抽象方法是沒有方法體的

3.如果一個類繼承了一個抽象類(如果這個抽象類還繼承了另一個抽象類),那麼這個類就要實現所有的抽象方法,否則,就將這個類也聲明為抽象類

抽象類存在的最大意義就是被繼承,因為抽象類是不能被例項化的,如果我們在後面的程式碼中不小心例項化了,那麼編譯器就會報錯,這樣就能達成一個檢驗的作用。因此我們要給予每個類最符合它們需求的限制,讓我們的程式碼變得更加安全。

介面

介面,你可以理解為100%的抽象類,因為抽象類裡面我們是可以包含普通方法的,但是接口裡面的方法全部預設為抽象方法,接口裡面的欄位全部預設為public static final類型。介面的關鍵字是interface ,子類來實現(繼承)介面使用關鍵字implements

下面給出具體的程式碼例項

那麼實現介面有什麼好處呢?

好處就是讓程式設計師不再去關注類是什麼類型,而是去關注這個類是否實現了我想要的介面,如果實現了,我就可以用,根本不用管這是什麼類。

另外要注意,介面可以繼承介面,一個類可以實現多個介面,但只能繼承一個父類。

小結

對於抽象類與介面的認識也就差不多了,要注意,抽象類啊,介面啊這些東西都是為了服務多型這樣一種靈活的設計方式。因此在我們使用多型去設計一些程式碼時,我們就可以嘗試使用抽象類或者介面。

如果你對java裡面的繼承與多型的思想以及程式碼實現已經有所瞭解了,那麼這篇文章想要傳達的知識也就完成了。

今日份分享已結束,請大家多多包涵和指點!


IT145.com E-mail:sddin#qq.com