0%

Multiple Inheritance, Interface and Mixin

最近看了Mixin之後,抒發一下自己的感想。
學過Software Engineering的,都知道DRY。如何共用程式碼就變成一門學問了。

假設我們現在有IA, IB, IC三個interface,然後有三個Concrete Class CA, CB, CC實作這三個介面
然後D, E兩個Class需要同時支援這三個interface,該怎麼做。

在C++這種支援Multiple Inheritance特性的語言,大概會是這個樣子。

lang: cpp
1
2
class D : public CA, CB, CC {};
class E : public CA, CB, CC {};

如果CA, CB, CC的內容風馬牛不相及,這個解決方案不錯,不然的話,Diamond Problem是個很頭大的問題。

而Java等語言等只支持單一繼承,因此避掉了Diamond Problem,不過卻引來其他問題。
有兩種常見的問題,第一種是實作介面。

1
2
class D implements IA, IB, IC {};
class E implements IA, IB, IC {};

假設某個Class的實作方式需要修改,需要修改,那麼D跟E的內容都需要修改。如此一來就達不到DRY的精神了。
另一種是亂七八糟的繼承方式。

1
2
3
4
5
6
7
class PD1 extends CA {};												class PE1 extends CA {};
class PD2 extends CB {}; class PE2 extends CB {};
class PD3 extends CC {}; class PE3 extends CC {};
class PD4 extends PD1 {}; class PE4 extends PE1 {};
class PD5 extends PD2 {}; class PE5 extends PE2 {};
class PD6 extends PD3 {}; class PE6 extends PE3 {};
class D extends PD6 {}; class E extends Pe6 {}

雖然避掉的第一個問題,不過那眼花撩亂的繼承關係更麻煩了。

至於動態語言大行其道之後,Mixin提供另外一種思考模式。由於Duck Typing的支持,類與類之間沒有強烈的interface contract關係。以Ruby來說

lang: ruby
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module IA 
end
module IB
end
module IC
end
class D
include IA
include IB
include IC
end
class E
include IA
include IB
include IC
end

mixin是一群method的集合,只要外在的class有滿足條件(Duck Typing),這個方案可以滿足大部分的需求。