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