假设您在Ruby中执行此操作:
ar = [1, 2]
x, y = ar
然后,x == 1和y == 2.我可以在自己的类中定义一个能产生相同效果的方法吗? e.g。
rb = AllYourCode.new
x, y = rb
到目前为止,我所能完成的任务就是使x == rb和y = nil。 Python有这样的功能:
>>> class Foo:
... def __iter__(self):
... return iter([1,2])
...
>>> x, y = Foo()
>>> x
1
>>> y
2
答案 0 :(得分:7)
是的。定义#to_ary
。这将使您的对象被视为一个用于赋值的数组。
irb> o = Object.new
=> #<Object:0x3556ec>
irb> def o.to_ary
[1, 2]
end
=> nil
irb> x, y = o
=> [1,2]
irb> x
#=> 1
irb> y
#=> 2
#to_a
和#to_ary
之间的区别在于#to_a
用于尝试转换
数组的给定对象,如果我们可以将给定对象视为数组,则#to_ary
可用。这是一个微妙的差异。
答案 1 :(得分:2)
几乎:
class AllYourCode
def to_a
[1,2]
end
end
rb = AllYourCode.new
x, y = *rb
p x
p y
Splat会尝试调用to_ary
,然后尝试调用to_a
。我不确定你为什么要这样做,这实际上是一个语法特性恰好在其实现中使用Array
,而不是Array
的一个特性。
换句话说,多次分配的用例是:
# swap
x, y = y, x
# multiple return values
quot, rem = a.divmod(b)
# etc.
name, age = "Person", 100
换句话说,大部分时间(Array
)分配的对象都不明显。
答案 2 :(得分:1)
您无法重新定义分配,因为它是运算符而不是方法。但是如果您的AllYourCode类要从Array继承,那么您的示例将起作用。
当Ruby遇到一个赋值时,它会查看右侧,如果有多个右值,它会将它们收集到一个数组中。然后它看着左侧。如果那里有一个左值,则为其分配数组。
def foo
return "a", "b", "c" # three rvalues
end
x = foo # => x == ["a", "b", "c"]
如果有多个左值(更具体地说,如果它看到逗号),它会连续分配rvalues并丢弃额外的值。
x, y, z = foo # => x == "a", y == "b", z == "c"
x, y = foo # => x == "a", y == "b"
x, = foo # => x == "a"
如果您发现了数组,也可以进行并行分配。
def bar
["a", "b", "c"]
end
x = bar # => x == ["a", "b", "c"]
x, y, z = bar # => x == "a", y == "b", z == "c"
x, y = bar # => x == "a", y == "b"
x, = bar # => x == "a"
因此,在您的示例中,如果rb是一个数组或继承自Array,则将为x和y分配其前两个值。