2009-04-20 55 views
5

假設你在Ruby中做到這一點:使對象的行爲就像紅寶石並行分配數組

ar = [1, 2] 
x, y = ar 

然後,X == 1和y == 2.是否有我可以定義一個方法我自己的類會產生相同的效果?例如

rb = AllYourCode.new 
x, y = rb 

到目前爲止,我已經能夠用這樣的賦值操作是使X == RB和y =零。 Python有這樣一個特點:

>>> class Foo: 
...  def __iter__(self): 
...    return iter([1,2]) 
... 
>>> x, y = Foo() 
>>> x 
1 
>>> y 
2 
+0

完美,謝謝,這正是我需要在這一秒。 – 2009-10-24 18:45:10

回答

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

你不能重新分配,因爲它是一個經營者,而不是一個方法。但是如果你的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是一個數組或從數組繼承,x和y將被賦予其前2個值。

+0

我想你的意思是在你的第一個例子中圍繞「a」,「b」,「c」括號。當我嘗試它時,出現語法錯誤。 – allyourcode 2009-04-20 22:24:43

+0

其實我忘了「迴歸」。現在修復。 – 2009-04-21 00:00:10

2

差不多:

class AllYourCode 
    def to_a 
    [1,2] 
    end 
end 

rb = AllYourCode.new 
x, y = *rb 
p x 
p y 

啪會嘗試調用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

這有些幫助,但我討厭它,當我問一個問題,人們相信我沒有很好的理由去做我想做的事情。如果您認爲這是一個糟糕的主意,請解釋原因!我很欣賞你的例子,但是顯示典型用法並不能解釋我想要做什麼的錯誤:/ – allyourcode 2009-04-20 22:35:33