要编写splat运算符的自定义结果,必须实现to_a
方法。 String类的示例:
class String
def to_a
self.split //
end
end
irb> res = *'text'
=> ["t", "e", "x", "t"]
但是如果没有上面的monkeypatch,String类对to_a
方法一无所知:
irb> String.respond_to? :to_a
=> false
所以问题是,在标准的“未修补”的String对象上应用splat运算符时会调用什么方法?
irb> res = *'text'
=> ['text']
答案 0 :(得分:5)
首先关闭:调用String.respond_to?(:to_a)
将不告诉您字符串 instance 是否响应to_a
,它会告诉您String
是否to_a
1}} class 回复to_a
。如果您想知道字符串是否响应'text'.respond_to?(:to_a) # => false
,您必须询问字符串:
String
或者您可以询问to_a
类是否有公共实例方法String.public_instance_methods.include?(:to_a) # => false
:
String
现在,原因为什么to_a
不响应a = *'text'.chars # => ['a', 'b', 'c']
a = *'text'.codepoints # => [116, 101, 120, 116]
a = *'text'.bytes # => [116, 101, 120, 116]
a = *'text'.lines # => ['text']
是因为它不清楚你想要什么:你想要一个字符数组吗?字形?线?代码点?字节?
{{1}}
至于为什么splat运算符的行为与你看到的一样,这似乎是语言规范中的一个极端情况。我甚至不能100%确定这是预期的行为。多个赋值的规范大约有4页,详见Ruby语言规范的第11.4.2.4节。
答案 1 :(得分:3)
Splat, by definition, returns the value in an array if the object doesn't respond to to_a
:
it "assigns the splatted object contained into an array when the splatted object doesn't respond to to_a" do
a = *1; a.should == [1]
end
警告:有点非官方,但相对有用。
答案 2 :(得分:1)
我不确定这是否足以满足您的需求,但您可以这样做:
1.9.3-p0 :008 > res = *'text'.chars
=> ["t", "e", "x", "t"]