当我们谈到继承,我们通常会分开为接口继承和实现继承。如果是单继承,无论是实现继承还是接口继承,都容易理解和使用。即便如此,在C++的著作中,还是提到当我们在继承一个类的时候,不仅仅要想到继承了实现,还要想到一并继承了接口。
多继承更是复杂,很容易走到菱形继承这样一个怪圈。在C#中,只有接口的多继承,并没有实现的多继承——我们不可以指定两个或两个以后的类作为父类。
Ruby中的Mixin是对多重实现继承的一个实现,即实现部分以模块的方式单独出来,模块有其特有的属性,比如不能实例化,不能继承别的类和被别的类继承等 。松本有一个例子很好:
module WriteStream
def write(str)
puts str
end
def conflict
puts "conflict"
end
end
module ReadStream
def read
puts "read data"
end
def conflict
puts "conflict-read"
end
end
class Stream
def getstream
puts "get stream"
end
end
class ReadWriteStream < Stream
include WriteStream
include ReadStream
end
rw = ReadWriteStream.new
rw.getstream
rw.read
rw.write("haha")
rw.conflict
这个例子就是网络编程中常常会用到的Stream
, ReadStream
, WriteStream
, ReadWriteStream
,在C++中这常常是一个菱形继承,而Ruby巧妙地采用了Mixin,从而避免了菱形继承。
在Ruby下的运行结果为:
get stream
read data
haha
conflict-read
即使这样,还是回避不了最根本的问题:方法Resolve,即决定到底使用谁的方法。我们在上例中故意制造了一个冲突的方法conflict,我们从运行结果可以看到方法Resolve中结果是ReadStream的conflict方法。我们可以将程序的28行和29行对调:
include ReadStream
include WriteStream
这时我们再次运行这段脚本,结果如下:
get stream
read data
haha
conflict
注意最后一行,调用conflict方法结果的差别,我们可以知道Ruby中的Mixin是基于include时的顺序来决定方法调用的顺序。
Comments: