2016-03-08 51 views
0

我會嘗試用一個簡單的例子來說明這個問題的對象標識:更改形式參數

def enclose(x) 
    [x] 
end 

在我的應用程序,enclose做更復雜的東西,但在本質上它返回一個數組,內容其中完全由參數x的值決定。我可以用它這樣的:

foo = 'abcd' 
.... 
foo = enclose(foo) 

現在我的問題:是否可以寫一個方法enclose!,它只是通過其封閉的版本替換參數,這樣的例子可以寫成

foo = 'abcd' 
.... 
enclose!(foo) 

由於Ruby通過引用傳遞參數,我認爲這可能是可能的。天真的方法,

def enclose!(x) 
    x = [x] 
end 

不工作 - 我想這是因爲分配創建一個新的對象,並離開實際參數不變。

是否有辦法,我可以達到我的目標?我認爲在Smallalk中,會有一種方法become這會改變對象的身份,但是在Ruby中我沒有發現類似的東西。

+0

是不是'foo = enclose(foo)'你真正想要什麼? – Candide

+0

這是一樣的(你可以從我的帖子中看到),只是我想提一下變量'foo'一次。我從'chomp!'的String方法'chomp'中接受了這個想法,但是使用了'String',它可以工作,因爲您可以在不更改String對象身份的情況下更改字符串的內容。在我的情況下,某些任意類型的值將被更改爲'Array'類型的值,現在我意識到這在Ruby中是不可能的。 – user1934428

回答

1

還有一些關於如何ruby is pass by value, but the values are references有趣的職位。

歸結起來,你可以修改一個對象引用的變量,但是你不能改變它來引用另一個對象。

> a = [1] 
=> [1] 
> def add_a(array) 
> array << "a" 
> end 
=> :add_a 
> add_a a 
=> [1, "a"] 
> a 
=> [1, "a"] 
3

由於Ruby通過引用傳遞參數,我認爲這可能是可能的。

Ruby是通過值,而不是通過引用,你已經證明自己,因爲否則你的代碼將工作。

我想在Smallalk中,會有一種方法變成會改變對象的身份,但在Ruby中我沒有找到類似的東西。

沒有。 Ruby既沒有通過引用也沒有become:,你想要的只是不可能的。

1

有一種方法可以完成你要求的東西,但它不是很漂亮。 Ruby有這種綁定的概念(http://ruby-doc.org/core-2.2.0/Binding.html),這就像.NET中的CallContext

你可以做這樣的事情:

def enclose(x) 
    [x] 
end 

def enclose!(x, binding) 
    eval("#{x} = [#{x}]", binding) 
end 

foo = 'abcd' 
enclose!(:foo, binding) 
=> ["abcd"] 

在上面的腳本中,:foo意味着你傳遞變量的名稱和binding(上下文)在哪裏可以找到它的價值。然後你動態調用eval來評估賦值操作foo = [foo]