第1 關于"接口"
關于接口的問題老莊說對了,這個東西并不屬于面向對象的概念,而且在動態類型面向對象語言(比如Ruby, Smalltalk里),根本沒有這個東西。這是一個純粹的靜態類型面向對象語言的特性,或者直接說,接口就是一個純類型(Type)。還是上次的例子:



2

3

4

5

6

7

8



9


10

在我接觸Smalltalk的最開始的一段時間里,這種地方是讓我最難受,我已經習慣了用類型輔助我的思維,但是我發現我在Smalltalk里做不到,雖然我可以寫出





但是他卻不是一個接口,我可以很用


來構造一個Instrument之后在它之上調用playNote方法,然而我會得到一個messageNotUnderstand的錯誤,Smalltalk和Ruby里沒有Abstract的概念。也就是說abstract method,abstract class以及interface,都不是面向對象的概念(或者嚴格一些說,都不是面向對象的必須的概念),而是面向對象類型系統的概念。那么在Smalltalk里我們會怎么做呢?









對于playSoloOnInstrument:instrument,我們對于instrument的類型是有要求的,就是它必須能夠接受playNote這個消息。當然這個類型需要是隱性,我也可以對等的寫出靜態面向對象的代碼把這個隱性的類型顯示的表示出來:



2

3

同樣對于第二個方法我們也可以寫出來:



2

3

如果我們需要多于一個的消息也是一樣的,比如




同樣這個時候隱性的類型需要就是



2

3

4

那么接口是什么呢?我給出一個不確切的說法,interface是一個消息的發送者(sender)和一個消息的接受者(reciver)間的一種類型的約定,也就是說在我看來interface的用處主要在細粒度的顯式類型約定。我有一個同事,每次寫代碼都為一個Test Case所要測試的對象定義一個interface,每個interface都只有2-3個方法(lx同學夸你呢:D),這是很得interface之三味的用法。這種的做法對于在靜態的面向對象系統的好處我們在繼承里再論述。
至于老莊所說的接口是多繼承的一種代替品,這只不過是世俗的看法,在靜態類型的面向對象里,繼承至少有2個語義:
1.實現繼承,這個在Smalltalk,Ruby,C++里有,而在java里沒有,C++里是通過private extends來實現的



2

這也是C++里為數不多的subclass不是subtype的例子。
2.類型繼承,這個在C++和java里有,而在smalltalk,ruby有卻不明顯。
類型繼承的極致就是C++里的純虛父類



2

3

4

5

也就是java里的interface



2

3

4

因此,也就明了了,所謂“面向接口編程”是以類型作為約定的編程。我覺得這點大家一定不陌生,面向接口的編程里interface都很小而且約定明確。但是要說明一點的是,這個東西和"面向抽象而不要面向具體編程"其實還不一樣,所以這個東西也就僅僅能算是靜態類型面向對象的一個慣用法,還到不了原則這么高。
一個subclass要想不成為一個subtype,滿足如下條件即可:
1、subclass override其parent的一個方法。
2、保持type signature
3、violate其parent的一些重要property
即可