是否有任何用例我们会在已经是数组的对象上调用Array.to_a
和Array.to_ary
?
如果没有,为什么这些方法存在于Array类中?
答案 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
不是不同服装中的整数,它是完全不同的东西。)
数组,整数等也实现nil
,to_a
,to_ary
,to_i
等等这一事实意味着你可以对待 all < / em> array-like对象相同,多态。如果它是一个数组,一个堆栈,一个集合,一个树,一个枚举器,一个范围或其他什么都没关系。只要它可以有点地表示为数组,它就会响应to_int
,只要它实际上是一个数组(即使它的类不是to_a),它会回复Array
,您不必检查,因为它不重要。
但请注意,理想情况下这些情况应该很少见。一般来说,你应该关心对象是否可以自己迭代(即它响应to_ary
)。事实上,您可以使用数组执行的大部分操作,也可以使用任何其他each
,而不使用Enumerable
或to_ary
。那些应该是最后的手段。
答案 1 :(得分:0)
数组实现to_a
和to_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
方法,依此类推。