2016-03-08 57 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]