第1 關(guān)于"接口"
關(guān)于接口的問(wèn)題老莊說(shuō)對(duì)了,這個(gè)東西并不屬于面向?qū)ο蟮母拍睿以趧?dòng)態(tài)類(lèi)型面向?qū)ο笳Z(yǔ)言(比如Ruby, Smalltalk里),根本沒(méi)有這個(gè)東西。這是一個(gè)純粹的靜態(tài)類(lèi)型面向?qū)ο笳Z(yǔ)言的特性,或者直接說(shuō),接口就是一個(gè)純類(lèi)型(Type)。還是上次的例子:



2

3

4

5

6

7

8



9


10

在我接觸Smalltalk的最開(kāi)始的一段時(shí)間里,這種地方是讓我最難受,我已經(jīng)習(xí)慣了用類(lèi)型輔助我的思維,但是我發(fā)現(xiàn)我在Smalltalk里做不到,雖然我可以寫(xiě)出





但是他卻不是一個(gè)接口,我可以很用


來(lái)構(gòu)造一個(gè)Instrument之后在它之上調(diào)用playNote方法,然而我會(huì)得到一個(gè)messageNotUnderstand的錯(cuò)誤,Smalltalk和Ruby里沒(méi)有Abstract的概念。也就是說(shuō)abstract method,abstract class以及interface,都不是面向?qū)ο蟮母拍睿ɑ蛘邍?yán)格一些說(shuō),都不是面向?qū)ο蟮谋仨毜母拍睿敲嫦驅(qū)ο箢?lèi)型系統(tǒng)的概念。那么在Smalltalk里我們會(huì)怎么做呢?









對(duì)于playSoloOnInstrument:instrument,我們對(duì)于instrument的類(lèi)型是有要求的,就是它必須能夠接受playNote這個(gè)消息。當(dāng)然這個(gè)類(lèi)型需要是隱性,我也可以對(duì)等的寫(xiě)出靜態(tài)面向?qū)ο蟮拇a把這個(gè)隱性的類(lèi)型顯示的表示出來(lái):



2

3

同樣對(duì)于第二個(gè)方法我們也可以寫(xiě)出來(lái):



2

3

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




同樣這個(gè)時(shí)候隱性的類(lèi)型需要就是



2

3

4

那么接口是什么呢?我給出一個(gè)不確切的說(shuō)法,interface是一個(gè)消息的發(fā)送者(sender)和一個(gè)消息的接受者(reciver)間的一種類(lèi)型的約定,也就是說(shuō)在我看來(lái)interface的用處主要在細(xì)粒度的顯式類(lèi)型約定。我有一個(gè)同事,每次寫(xiě)代碼都為一個(gè)Test Case所要測(cè)試的對(duì)象定義一個(gè)interface,每個(gè)interface都只有2-3個(gè)方法(lx同學(xué)夸你呢:D),這是很得interface之三味的用法。這種的做法對(duì)于在靜態(tài)的面向?qū)ο笙到y(tǒng)的好處我們?cè)诶^承里再論述。
至于老莊所說(shuō)的接口是多繼承的一種代替品,這只不過(guò)是世俗的看法,在靜態(tài)類(lèi)型的面向?qū)ο罄铮^承至少有2個(gè)語(yǔ)義:
1.實(shí)現(xiàn)繼承,這個(gè)在Smalltalk,Ruby,C++里有,而在java里沒(méi)有,C++里是通過(guò)private extends來(lái)實(shí)現(xiàn)的



2

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



2

3

4

5

也就是java里的interface



2

3

4

因此,也就明了了,所謂“面向接口編程”是以類(lèi)型作為約定的編程。我覺(jué)得這點(diǎn)大家一定不陌生,面向接口的編程里interface都很小而且約定明確。但是要說(shuō)明一點(diǎn)的是,這個(gè)東西和"面向抽象而不要面向具體編程"其實(shí)還不一樣,所以這個(gè)東西也就僅僅能算是靜態(tài)類(lèi)型面向?qū)ο蟮囊粋€(gè)慣用法,還到不了原則這么高。
一個(gè)subclass要想不成為一個(gè)subtype,滿(mǎn)足如下條件即可:
1、subclass override其parent的一個(gè)方法。
2、保持type signature
3、violate其parent的一些重要property
即可