當我們談到繼承,我們通常會分開為介面繼承和實現繼承。如果是單繼承,無論是實現繼承還是介面繼承,都容易理解和使用。即便如此,在C++的著作中,還是提到當我們在繼承一個類的時候,不僅僅要想到繼承了實現,還要想到一併繼承了介面。
多繼承更是複雜,很容易走到菱形繼承這樣一個怪圈。在C#中,只有介面的多繼承,並沒有實現的多繼承——我們不可以指定兩個或兩個以後的類作為父類。
Ruby中的Mixin是對多重實現繼承的一個實現,即實現部分以模組的方式單獨出來,模組有其特有的屬性,比如不能執行個體化,不能繼承別的類和被別的類繼承等 。松本有一個例子很好:
module WriteStreamdef write(str)puts strenddef conflictputs "conflict"endendmodule ReadStreamdef readputs "read data"enddef conflictputs "conflict-read"endendclass Streamdef getstreamputs "get stream"endendclass ReadWriteStream < Streaminclude WriteStreaminclude ReadStreamendrw = ReadWriteStream.newrw.getstreamrw.readrw.write("haha")rw.conflict
這個例子就是網路編程中常常會用到的Stream,ReadStream,WriteStream, ReadWriteStream,在C++中這常常是一個菱形繼承,而Ruby巧妙地採用了Mixin,從而避免了菱形繼承。
在Ruby下的運行結果為:
get streamread datahahaconflict-read
即使這樣,還是迴避不了最根本的問題:方法Resolve,即決定到底使用誰的方法。我們在上例中故意製造了一個衝突的方法conflict,我們從運行結果可以看到方法Resolve中結果是ReadStream的conflict方法。我們可以將程式的28行和29行對調:
include ReadStreaminclude WriteStream
這時我們再次運行這段指令碼,結果如下:
get streamread datahahaconflict
注意最後一行,調用conflict方法結果的差別,我們可以知道Ruby中的Mixin是基於include時的順序來決定方法調用的順序。