我可以写一个简短的示例来验证内部to_a
Enumerable
个each
调用class MyFooClass
include Enumerable
def initialize
@members = [1, 2, 3]
end
def each
puts "each is now called"
@members.each{ |m| yield(m) }
end
end
a = MyFooClass.new
puts "let us convert to array"
g = a.to_a
。这是:
let us convert to array
each is now called
输出结果为:
each
请注意,Enumerable
不是to_a
的成员,而是each
。另外,如果我从我的类中删除in `to_a': undefined method `each' for #<MyFooClass:0x997c1ac @members=[1, 2, 3]> (NoMethodError)
的定义,则代码会崩溃,并显示以下消息:
to_a
我想知道是否有关于此的Ruby官方文档,这将记录Enumerable
(each
的成员)在您的班级中通过to_a
方法的事实。请不要指导我{{1}}的源代码。我不认为这是一个答案。
答案 0 :(得分:5)
来自fine manual:
Enumerable
mixin为集合类提供了多种遍历和搜索方法,并具有排序功能。 该类必须提供方法each
,这会产生集合的连续成员。
强调我的。所以Enumerable的所有迭代行为都基于类的each
方法; Enumerable接口(min
,max
,sort
)的排序部分使用<=>
,但这里并不重要。
提供的each
方法是Enumerable与混合它的类进行交互的唯一定义方式.Enumerable提供to_a
方法,因此必须使用each
来实现它
顺便说一下,Enumerable最好不要调用to_a
,除非必须这样做,它会尝试将所有内容保存为Enumerable,以避免耗尽枚举来构建一个在两个时间都很昂贵的数组和空间。 Yossi指出的答案更多地是关于当 Enumerable调用to_a
而非如何时(但答案仍然是有趣的读取)。< / p>
答案 1 :(得分:1)
请注意#to_a
代码中的id_each
:
static VALUE
enum_to_a(int argc, VALUE *argv, VALUE obj)
{
VALUE ary = rb_ary_new();
rb_block_call(obj, id_each, argc, argv, collect_all, ary);
OBJ_INFECT(ary, obj);
return ary;
}
有关更深入的说明,请参阅this问题。
答案 2 :(得分:0)
除了mu指出的手册中的禁欲主义解释之外,在Pickaxe书中还有following passage,这是Ruby介绍性书籍的真实之王:
好吧,你的课程可以支持所有这些整洁的功能,多亏了 mixins和模块的魔力Enumerable。你所要做的就是写作 一个名为each的迭代器,它返回集合的元素 反过来。混入Enumerable,突然你的课程支持 例如map,include?和find_all?。