为什么Ruby Array类有to_a和to_ary方法?

时间:2017-05-25 17:50:14

标签: ruby-on-rails ruby

是否有任何用例我们会在已经是数组的对象上调用Array.to_aArray.to_ary

如果没有,为什么这些方法存在于Array类中?

3 个答案:

答案 0 :(得分:9)

  

是否有任何用例我们将这些强制方法(Array.to_a和Array.to_ary)称为已经是Array的对象?

是的:在Ruby中,你通常从不关心对象是什么类的实例。只有它能做什么。所以,你只关心"这个对象可以将自己转换为数组"。显然,数组可以将自身转换为数组,因此它应该具有这些方法。

稍微长一点的回答:如果我们不关心某个对象是什么类的实例...那么我们为什么要关心它是否可以将自身转换为数组?嗯,这是一个务实的选择。从纯粹 OO的角度来看,它并不重要。但是出于效率和性能原因,某些操作在执行引擎的核心内部实现,要求某个对象属于某个类。换句话说,有时对象无法工作,您需要一个抽象数据类型。

例如,Ruby执行引擎内部有一些操作可以利用他们了解Array s内部内存布局的事实。显然,如果你把那些 Array的东西递给他们并且他们在那个对象的记忆中徘徊,那些操作就会以可怕的方式破坏。从纯OO的角度来看,这些操作不应该知道,他们应该使用Array的公共界面,但是,他们不会。但是,为了给你(程序员)一个类似于数组的对象的逃生舱口,这些操作将允许你首先通过调用Array将自己转换为to_ary

换句话说,实现to_ary意味着您的对象是一种类型的数组。显然,数组是一种数组,这就是它响应to_ary的原因。

Ruby中还有其他类似的转换方法:字符串to_str,整数to_int,浮点数to_float,"函数"

还有他们的单字母变体。长变种意味着"我真的是一个数组,我只是碰巧不是to_proc类的实例。"相反,简短的变体意味着"我可以将我自己称为数组"。

您可以看到最明显的Array:它响应nil(因为它有点意义将to_i表示为整数nil),但是它没有回应0(因为to_int 不是不同服装中的整数,它是完全不同的东西。)

数组,整数等也实现nilto_ato_aryto_i等等这一事实意味着你可以对待 all < / em> array-like对象相同,多态。如果它是一个数组,一个堆栈,一个集合,一个树,一个枚举器,一个范围或其他什么都没关系。只要它可以有点地表示为数组,它就会响应to_int,只要它实际上一个数组(即使它的类不是to_a),它会回复Array,您不必检查,因为它不重要

但请注意,理想情况下这些情况应该很少见。一般来说,你应该关心对象是否可以自己迭代(即它响应to_ary)。事实上,您可以使用数组执行的大部分操作,也可以使用任何其他each,而不使用Enumerableto_ary。那些应该是最后的手段。

答案 1 :(得分:0)

数组实现to_ato_ary,因为这允许将参数强制转换为特定类型的更简洁方法。

例如,如果你有一个方法怎么办:

def foo(object)
  #does some work on object that requires object acts like an array.
  ...
end

并希望在代码中其他位置生成的集合上使用此方法。

您可以这样做的一种方法是在执行操作之前强制转换object.to_a

def foo(object)
  array = object.to_a
  ...
end

如果Array没有实现to_a,那么您必须进行检查:

def foo(object)
  array = object.to_a if object.respond_to?(:to_a)
  ...
end

答案 2 :(得分:0)

我认为(除其他事项外)避免为nil设置特殊情况。

我们说foo是一种可以返回数组或nil的方法。下面的片段会在一半的时间内失败:

foo.each { |x| puts x }

如果Array没有实施to_a方法,你可能不得不写这样的东西,在我看来有点难看:

(foo || []).each { |x| puts x }

而不是:

foo.to_a.each { |x| puts x }

以类似的方式,Integer使用to_i方法,String使用to_s方法,依此类推。