你们公司内部肯定是属于沟通密集型。而社区比较松散吧。 这个我想没什么规律吧。 还没听说有多少公司统计这个的。
哈哈,今天我也发了个重复的老帖子
@luikore 再补充一点:你在楼上举的那个例子,所谓的菱形问题,是个伪问题,Ruby 里根本不存在这样的问题。
多重继承是描述类之间的关系,而组合,描述的是对象之间的关系,当然,如果你只从方法集合这个层面来说,Mix-in 是一种组合方式,也能说的通。
继承是 is_a,组合是 has_a, 你把 Module 理解为一个方法集合,当然是组合了,这个类 include 了 module,它的对象就可以 has_a 这个方法,has_a 那个方法。
而且 Module 本身是 Class 的父类, Class.superclass #=> Module
include 也是在 Module 中被定义的私有方法,如果你 include 一个模块,那么会把这个模块加到这个类的继承树里,请问用组合的概念如何解释这一行为?
所以得出的结论是,如果你只把 Mix-in 当作一个方法集合,而不关注类和模块的关系,那可以理解为组合,但这只是表面,当然理解到这一层,不影响编写代码了。但可能会碰到奇怪的问题,比如你举的那种菱形问题,会让你迷惑。
真正理解了 Mix-in 是多重继承(不是传统的多重继承,继承关系是单一的,又有多重继承的共用方法,不要用 C++ 那种多重继承去理解)这个概念, 「你说的:编程时不好确定调用到哪里」,这种问题也不会存在了。
关于这个问题,我不继续讨论了。毕竟每个人有每个人的理解,我只是传达了 Matz 在他书里的论述。大家能怎么理解就怎么理解吧。
#46 楼 @luikore 本来就是继承嘛,为什么要避免呢, 《松本行弘的程序世界》31 页里面 Matz 解释的很清楚嘛。或者说,Mix-in 是 Ruby 里实现多重继承的方式,而且通过 Mix-in 这种方式,降低了传统多重继承的复杂性,更进一步说,Mix-in 是经过 Matz 改良的 Ruby 里实现多重继承的方式。
你说 35 页里写:多重继承相当于语言功能支持模块组合。
原文里还有前面一句话,假如把类当模块来看的话。而且,那句话的章节标题就是:动态编程语言也需要多重继承。
现在是模块是类,Mix-in 模块算是一种抽象类。它只是有限制,都是 Class 类的子类。
Matz 那本书里第二章基本通篇在说继承和多重继承与 Mix-in 的。
我为什么要和你讨论呢,就是因为你说「Mix-in 不是继承」,可它明明就是继承,你为什么要避免增加它外延,我也没有增加其外延,我说的就是多重继承,多重继承不也是一种继承嘛。Ruby 里的继承一般是指类和类之间的关系,而类和多个模块的时候,就是 Mix-in,多重继承。
所以我说,Mix-in 的实质是多重继承的一个实现方式。这就是讨论的意义所在。
你说的这句,[我说的是编程时不好确定调用到哪里,你说的是运行时这个东西是确定的] ,我也认同,楼上就认同了,我说你阐述的是一种编程方法,但是你用编程方法来理解 Mix-in 的工作原理实现方式,我就不认同了。
而且,matz 也说了,继承就是利用模块的方法(34 页)。
我说 Mix-in 是一种继承,你说继承是一种组合方式。
http://ruby-china.org/topics/11249
这也有个评测,你可以看看。 说明的是 Goliath 不用 Grape 也可以。
#2 楼 @shell 嗯,异步。你可以去了解一下: https://github.com/postrank-labs/goliath
推荐 Goliath
#39 楼 @simlegate 多看几遍吧,尤其是前几章讲他设计 Ruby 的过程。这本书不是教你 Ruby 语法的。比如第 30 页和 31 页,你就可以看到 Mix-in 和多重继承的关系,引导你解决一些问题。你就不会在 module 和 class 的关系上感到迷惑了。「原文:对 Mix-in 的理解是,Mix-in 只不过是实现多重继承的一个技巧而已。Ruby 只支持 Mix-in 形式的多重继承。Matz 也说了,曾有一个著名的青年学者因为 Ruby 的原因而误认为多重继承和 Mix-in 是不同的概念,这个让 Matz 有点惭愧,他觉得这些误解部分是他造成的,哈哈。」
还有很多地方: 「Mix-in 是使类结构变的简单的优秀技术。Mix-in 使多重继承的类形成非常清晰的树结构,没有变成网状结构。」如果非要使用组合的概念去理解 Mix-in,正好和 Matz 设计 Mix-in 的初衷相悖,让 Matz 情以何堪。
#37 楼 @simlegate 因为 Ruby 太灵活了啊,如果不把握一些实质,很容易被 Ruby 搞晕。所以我推荐去看 Matz 的书,看他设计 Ruby 的初衷和原则,对于我们理解 Ruby 里面的概念很有帮助。这可比看源码实际多了。
#35 楼 @nickelchen 去看 Matz 的《松本行弘的程序世界》一书吧,从 Matz 如何设计 Ruby 里面可以看出,Mix-in 正好解决了传统的多继承的问题,降低了复杂性,就像我楼上说的,Matz 设计 Mix-in 的这种机制,就是为了让程序员可以像单继承那样去使用多继承。所以不要和 C++ 的多继承去比,如果一定要比,Ruby 的实现和 Java 的更类似。
只有理解了这个实质,写代码的时候才不容易被 Mix-in 搞晕啊。
#33 楼 @alan90121 嗯。刚开始 simlegate 打错字了,实例方法打成了实例变量,所以我看着有点奇怪。
在 Ruby 里面,很大的数字被存储为 Bignum 对象,实在要研究,你可以看看 Bignum 的源码。
#20 楼 @goinaction 好吧,我想也不应该是 bug,否则在 Ruby2.0 里应该被改了。以后使用的时候需要小心。
@Msms 晕了。 yield 的作用是「转让」块代码,块代码可以看做是一个匿名函数。记住这一条原则就可以了。Ruby 灵活多变,我们需要抓住一条不变的实质,才能处理一些问题。否则的话,看在眼里都是奇怪的结果。
test_yield("locale", ["name","desc"], "locale") do |arr, locale|
puts arr.class.to_s
puts arr.to_s
end
相当于
def test_yield (select_locale,value,locale)
#经过yield,把块代码压入方法堆栈
f(arr, locale){
puts arr.class.to_s
puts arr.to_s
}
yield value 这里 yield 后面的参数就是传递给块那个匿名方法参数的。所以要注意参数个数(块里的参数)。
@ihlayy 总结的也很好,只是感觉没说到点子上。
果然是坑。这应该算 bug 吧。
嗯,很不错。资料有点旧了,但不影响学习。
一个对象,可以理解为类和实例对象,本身类也算是 Class 的一个实例对象。 单例方法,如果是类的单例方法,那就是类方法,你想在另一个类里调用这个类的类方法,可以这样。
class A
def self.test
puts "hello"
end
end
class B
def self.test
A.test
end
end
如果是实例对象。
module A
def test
"hello"
end
end
class B;end
class C;end
b = B.new
c = C.new
b.extend A
c.extend A
b.test
c.test
实例对象的单例方法,你无法在另一个对象中直接调用,因为在另一个对象中找不到那个方法,只会把它当实例变量去处理。