13

据推测,Matz 说“mixin 几乎可以完成多重继承所做的所有事情,而没有相关的缺点”(Matz 的话)。

首先,为什么 Ruby 模块包含不是“多重继承”?在我看来,模块和类之间几乎没有区别。当模块用作超类时,您无法实例化模块这一事实无关紧要。

我也知道连续的模块包含形成了一个从类向上延伸的单一继承链(不是树)。但是,对我来说,这不足以将它与“多重继承”区分开来,因为 Python 多重继承系统也“线性化”了超类链(使用C3 算法),只是 Ruby 的“线性化”过程要简单得多。

那么,在像 Python 这样的语言中,Ruby 模块混合与多重继承到底有什么区别呢?为什么 Python 采用 c3 MRO 算法背后的论点不适用于 Ruby?如果它们确实适用 - 为什么 Ruby 决定不采用这种算法?

谢谢

4

4 回答 4

4

使用 MI,可以将出现的许多问题简化为实现细节;您不能笼统地谈论“多重继承”,而不谈论细节。因此,当您说“多重继承”时,我会假设您的意思是“C++ 多重继承”。

多重继承最常见的问题是钻石问题。如果同一级别的多个超类定义了相同的方法,如何知道子类调用了哪个方法?

使用模块,这个问题很容易解决——最后一个包含的模块总是“获胜”。你不能像 C++ 中的类那样“同时”包含多个模块。所以这个问题永远不会出现。

当模块用作超类时,您无法实例化模块的事实无关紧要

我恭敬地不同意。

首先,模块在 ruby​​ 中永远不会“用作超类”;只有超类是。

其次,对于多重继承,确切地知道构造函数(和析构函数!)被调用的顺序并不是一件小事。ruby 模块不允许实例化的事实完全抑制了这个问题。

于 2011-02-07T09:45:30.243 回答
3

代表 Mladen 将其添加为实际答案,因为我发现它非常有帮助,而且我猜对于 SO 用它做的任何疯狂的事情,答案都会得到更好的索引。

这是一篇关于这个问题的好文章,看看它是否回答了你的问题:http ://artima.com/weblogs/viewpost.jsp? thread=246488 – Mladen Jablanović 2010-10-28 18:23:23

于 2012-06-28T22:51:57.160 回答
0

查看 Pragmatic Press 的“Metaprogramming Ruby”一书。它以非常易于阅读和理解的方式包含对此的非常详细的解释。http://pragprog.com/titles/ppmetr/metaprogramming-ruby

我不能回答你的大部分问题,因为我不知道 python。但是为什么它不是多重继承的基础是当模块被包含或类被模块扩展时,ruby 将模块注入到继承链中。

class Foo
  include Bar
end

module Bar
end

foo = Foo.new

这会产生一个继承链,其中 foo 是 Foo 的一个实例,而 Foo 继承自 Bar。

它比这更棘手,并且继承注入发生的顺序有规则。我参考的书很好地解释了它。

于 2010-10-27T13:38:15.343 回答
0

ruby 中最重要的是您使用每个包含的模块覆盖以前的数据/函数定义。

所以这很糟糕,因为理论上每个新模块都应该注意访问被覆盖的先前代码。

所以编写新模块的示例代码是(逻辑上):

old_function = fun
fun = define_new_function
  do_you_staff
  call old_function

您不必使用旧函数,尽管在大多数情况下它很有用,但有时重写整个代码更容易。

每个包含的模块都会构建覆盖的方法链,因此多重继承不会有问题,但包含模块的顺序变得更加重要。

这种方法也称为猴子补丁——在 Ruby on Rails 中广泛使用的术语。

于 2010-11-16T00:40:16.280 回答