Jun'uary
Jan'uary » 日志 » 多重继承
多重继承
Jan 发表于 2007-10-24 14:01:04
忽然又有了一个恍然大悟的想法,那就是ruby对多重继承的设计真的很棒~
C++中的菱形继承一直被人抓着打,郁闷啊。比如说A派生出B, C, D多继承自B, C,那么,D里面会有两个A的核 - 双核,我已经忘记了C++是禁止这种继承的还是就让两个A同时存在与D里面(印象中是第二种处理吧)。曾经读到过一篇清华的博士论文,建议加入虚继承来处理菱形继承的问题,注意他所提出的虚继承并不是现在正在用的虚继承,而是改变现有的虚继承的语意,表明是一个菱形继承,详细我也不说了,忘光了,sigh
Java采取了一个更加SB的方法,在我看来还不如学C++。Java做出两个决定:一是继承只能有一个父类,二是加入Interface。这种设计直接导致在需要多继承的场合让程序民工们烦的要死,你不要告诉我那是我的设计有问题,你为什么不觉得是Java设计有问题?陷入一堆class abstract class interface之中想要理出一个完美的继承体系的时候真是感觉生不如死,这种麻烦大大削弱了面向对象的能力,完全是历史的倒退。
Ruby, 啧啧,Ruby,非常聪明的引进了一个新的东西,Module,是的,Ruby也限制你只能继承自一个父类,但是你可以无限制的include Module。当你第一眼看到它的时候也许会觉得Module和C里面的MACRO好像,然后把它忘在脑后,可是实际上Module是一个更加面向对象更加高明的设计,它的作用其实是把多重(树形)继承自动的转化成单(链式)继承,当你想要D继承自B, C时,C++/Java的继承图像是这样的:
B ->
D
C ->
Ruby是这样的
B -> C -> D
这里假设我们把C设计为Module。当你include C的时候,c代码会为你创建一个新类,它拥有Module的所有实例变量和方法,同时以B作为这个新类的父类,然后再把D的继承指针指向这个新的类,我们称之为C'好了。这样D就同时拥有了B和C的方法。
在菱形继承的时候,我们把A, B, C都设计为Module, 即B inlucde A, C include A,然后class D include B, C。在Ruby中Module实际上是Class的父类,但Module本身也是一个Class。。。有点绕口。。。Module除了不能在Ruby的层次上被实例化以外,其他和Class并无太大区别。所以这样的设计并没有什么怪异的。最后我们的菱形继承会成为这样:
A->B'->C'->D
由于Module不能实例化,这必然使得Ruby需要另外一个设计,弱类型以及Duck typing。要在c++里面使用多态,你必须这样int lala(A a),也就是用父类来做占位符,如果Ruby也要这样就完了:既然Module不能实例化,那用什么来做占位符?所以Ruby是弱类型, 你def lala(a)就好了,不用声明a是什么类型,只要a有A的方法,我们就认为它是A的实例,这样多态(Duck Typing)就成为很容易的事情了。
不要觉得弱类型有什么不好,真的,利远大于弊。
C++中的菱形继承一直被人抓着打,郁闷啊。比如说A派生出B, C, D多继承自B, C,那么,D里面会有两个A的核 - 双核,我已经忘记了C++是禁止这种继承的还是就让两个A同时存在与D里面(印象中是第二种处理吧)。曾经读到过一篇清华的博士论文,建议加入虚继承来处理菱形继承的问题,注意他所提出的虚继承并不是现在正在用的虚继承,而是改变现有的虚继承的语意,表明是一个菱形继承,详细我也不说了,忘光了,sigh
Java采取了一个更加SB的方法,在我看来还不如学C++。Java做出两个决定:一是继承只能有一个父类,二是加入Interface。这种设计直接导致在需要多继承的场合让程序民工们烦的要死,你不要告诉我那是我的设计有问题,你为什么不觉得是Java设计有问题?陷入一堆class abstract class interface之中想要理出一个完美的继承体系的时候真是感觉生不如死,这种麻烦大大削弱了面向对象的能力,完全是历史的倒退。
Ruby, 啧啧,Ruby,非常聪明的引进了一个新的东西,Module,是的,Ruby也限制你只能继承自一个父类,但是你可以无限制的include Module。当你第一眼看到它的时候也许会觉得Module和C里面的MACRO好像,然后把它忘在脑后,可是实际上Module是一个更加面向对象更加高明的设计,它的作用其实是把多重(树形)继承自动的转化成单(链式)继承,当你想要D继承自B, C时,C++/Java的继承图像是这样的:
B ->
D
C ->
Ruby是这样的
B -> C -> D
这里假设我们把C设计为Module。当你include C的时候,c代码会为你创建一个新类,它拥有Module的所有实例变量和方法,同时以B作为这个新类的父类,然后再把D的继承指针指向这个新的类,我们称之为C'好了。这样D就同时拥有了B和C的方法。
在菱形继承的时候,我们把A, B, C都设计为Module, 即B inlucde A, C include A,然后class D include B, C。在Ruby中Module实际上是Class的父类,但Module本身也是一个Class。。。有点绕口。。。Module除了不能在Ruby的层次上被实例化以外,其他和Class并无太大区别。所以这样的设计并没有什么怪异的。最后我们的菱形继承会成为这样:
A->B'->C'->D
由于Module不能实例化,这必然使得Ruby需要另外一个设计,弱类型以及Duck typing。要在c++里面使用多态,你必须这样int lala(A a),也就是用父类来做占位符,如果Ruby也要这样就完了:既然Module不能实例化,那用什么来做占位符?所以Ruby是弱类型, 你def lala(a)就好了,不用声明a是什么类型,只要a有A的方法,我们就认为它是A的实例,这样多态(Duck Typing)就成为很容易的事情了。
不要觉得弱类型有什么不好,真的,利远大于弊。
曾经的这一天...
- » 2006年: Pi
相关日志:
收藏:
QQ书签
del.icio.us
订阅:
Google
抓虾
最新评论
-
2007-12-13 02:57:07 匿名 221.218.*.*
LZ不是没想法, 但是想法太单纯.. 只能说你干的那些工作适合弱类型罢了...
-
2007-12-14 03:33:54
帅哥,我干的哪些工作?
-
2007-12-23 17:05:40 匿名 221.219.*.*
由于Module不能实例化,这必然使得Ruby需要另外一个设计,弱类型以及Duck typing
请问,这有什么必然性?? -
2007-12-24 01:32:01
没有Duck Typing, Ruby怎么利用多态? 前面说过mixin实际上是一种继承,ruby中B mixin了module A相当于Java中B extend了A.在Java中我们可以写void func(A a)来利用多态,可以把B的对象传进去;但是在ruby里面不能这样写,因为B mixin A的时候,ruby创造了一个拥有类A所有方法的新类A', B是A'的子类而不是A的子类,所以你不能写void func(A a), 由于A'是ruby内部的类,在ruby外面是看不到的,所以你也没办法写void func(A' a). 但是只要设定成弱类型,引入duck typing,这个问题根本就不存在了,因为现在只需要写作void func(a).
