1. 程式人生 > >java程式設計思想讀書筆記一(面向物件)

java程式設計思想讀書筆記一(面向物件)

面向物件

我們常見的程式設計正規化有指令式程式設計函數語言程式設計邏輯式程式設計,而面向物件程式設計也是一種指令式程式設計。

指令式程式設計式面向計算機硬體的一種抽象,有變數(儲存單元),賦值語句(獲取儲存指令),表示式(記憶體引用和算術運算)和控制語句(跳轉指令),命令式程式就是對一個馮諾依曼機的指令序列的抽象,面向物件是對我們現實世界模型的一個抽象,之後在對映到馮諾依曼機的指令序列。

面向物件的基本特性

如果只是用變數,賦值語句,表示式,控制語句去構建現實世界模型的話會非常困難,所以面向物件的出現的根本原因就是就是為了解決這個問題,以及這個問題放在工程生產中產生的新的更為複雜的問題。

面向物件讓我們從指令程式碼操作變數轉變為通過指令操作物件。 當我們理解了這個以後再去看面向物件的基本特徵:

抽象
封裝

首先抽象就是建立一個對現實模型的抽象,封裝就是將變數,賦值語句,表示式,控制語句進行組合來描述上面的抽象,並且將他們“打包”,看成一個原子結構,之後的程式邏輯都是圍繞著這個原子結構進行的。

最後,面向物件的程式設計就是將原來的 ”模式一“ 改變為 ”模式二”

模式一:程式 = (賦值語句+表示式+控制語句)+ 變數

模式二:程式 = 物件 + 物件(物件之間的呼叫)

面向物件的高階特性

物件之間的關聯關係

抽象,封裝只是對現實模型和馮諾依曼機之間基本的對映關係,而現實世界中模型與模型之間還存在很多關係,如繼承、組合、依賴等。

而維護這些關係也成為面嚮物件語言的一個特性,並且有相應的語法支援。

1.繼承is-a組合:一個類繼承具有相似功能的另一個類,根據需要在所繼承的類基礎上進行擴充套件。
優點: 具有共同屬性和方法的類可以將共享資訊抽象到父類中,增強程式碼複用性,同時也是多型的基礎。
缺點: 子類中擴充套件的部分對父類不可見,另外如果共性比較少的時候使用繼承會增加冗餘程式碼。

2.組合has-a組合:has-a組合是在一個類中引用另一個類作為其成員變數。
優點: 可擴充套件性和靈活性高。在物件組合關係中應優先考慮has-a組合關係。
缺點: 具有共性的類之間看不到派生關係。

多型

多型在程式碼複用中起著尤為重要的作用,假如物件A依賴物件B,如果有物件C繼承物件B,則說明物件C包含物件B,所以當物件C向上轉型為物件B時不會出現資訊的丟失,大部分靜態程式語言都支援向上轉型。所以物件A對B的操作完全適用於C,所以當依賴B和依賴C時會有不同的表現,並且這個判斷過程實在執行期決定的。

public class A {
    public void fun(B b){
        b.fun();
    }
}

public class B {
    public void fun(){
        System.out.println("我是b");
    }
}

public class C extends B{
    //過載
    public void fun(){
        System.out.println("我是c");
    }
}

public class Test {
    public static void main(String[] args) {
        A a = new A();
        B b = new B();
        C c = new C();
        a.fun ( b );
        a.fun ( c );
    }
}
-------------------------------------------------
Output:
我是b
我是c

以上是最簡單的多型的例子,通過上面例子很難發現多型的好處,這樣做的意義是什麼?

觀察上面的程式碼會發現,A的fun()方法引數為B,但是如果傳遞別的型別可不可以?答案是可以的,因為上面的程式碼中我們傳遞了B的子類C,如果有D、E、F…都繼承B的話,也都可以傳遞到A的fun()中,所以起到了複用的作用。

但是還是體現不出來多型的好處,傳遞必須要繼承這個類,不符合現實模型,比如A是播放叫聲的裝置,B是斑點狗,所以將B傳遞進去時會播放斑點狗的叫聲,而C要是繼承B,在現實生活世界模型中,C也是斑點狗才行。

那如果我想播放牧羊犬的叫聲怎麼辦?用抽象類就可以。如果B是抽象類的話,抽象的是狗,所以C可以任何狗,因為B中的所有東西都是抽象的,沒有任何描述狗細節的東西,所以可以是任何狗。

最後還是發現不完善,那如果我要播放貓叫聲怎麼辦?這時候會有個比抽象類還抽象的東西,那就是介面,一個超級有用的傢伙,有了他就可以完全和現實世界模型對應起來了,因為介面抽象的是行為,所以當B為介面時,規定B有叫聲方法,所以當A的fun方法中傳遞的B介面時,就可以理解為,只要傳遞實現叫聲方法的就可以,無論什麼。所以當貓實現這個介面後,就可以被放到聲音播放器當中,同樣馬、豬、牛都可以,只要他們實現叫聲介面就行,但是樹可以吧?不可以,因為現實世界中的樹不可以叫。所以介面只抽象行為,完全可以實現現實模型的和麵向物件的對映。

所以抽象程度從小到大分別為類>抽象類>介面。

  1. 當B為類時,A只能接收B子類。
  2. 當B為抽象類時,A能接收符合這個抽象的具體。
  3. 當B為介面時,A能接收實現B介面的任何東西,在當前上下文中就是有叫聲的任何東西。

所以當B為普通類時,A就是一個 斑點狗叫聲播放器。當B為抽象類時,A就為一個 狗的叫聲播放器。而當B為介面時,A就是一個 叫聲播放器,可以播放任何聲音,這就是多型的意義。

一個斑點狗播放器和一個可以播放任何聲音的播放器不存在那個更好,要根據實際的場景進行判斷,一個作用域小一個作用域大。

其實在框架中或者“造輪子的人”用介面的比較多,而“用輪子的人”用普通類比較多,所以當閱讀原始碼發現各種介面時不要疑惑,那是多數是為了讓程式碼通用、作用域大。