2015-09-13 68 views
2

通過一種方法接收的參數是相同的對象的引用作爲傳遞給它的參數,例如:對象是否可以更改爲不同類的實例?

def object_id_of_param(object) 
    object.object_id 
end 

the_object = [1, 2, 3] 

the_object.object_id   # => 15247020 
object_id_of_param(the_object) # => 15247020 

如果調用對象的實例方法,該方法從任何修改就地對象參考對象,無論範圍,所有的變量引用單個對象本身修改原地的,如:

def modify_object(object) 
    object.map! { |n| n + 1 } 
end 

the_object = [1, 2, 3] 

the_object.object_id # => 18047480 
the_object # => [1, 2, 3] 

modify_object(the_object) 

the_object.object_id # => 18047480 
the_object.inspect #=> [2, 3, 4] 

如果你想要做別的事情到該對象並像的方法無法做到這一點,您可以使用[email protected]_variable_set來更改它(請參閱ndn's great answer)。

如果您嘗試將其完全更改爲其他類,則不起作用;以下方法不會修改原始對象。它不會將它從Array變成Time;它會導致在該方法中新object變量引用新Time對象:

def fail_to_modify_object(object) 
    object = Time.now 
end 

the_object = [1, 2, 3] 

the_object.object_id # => 14554660 
the_object.inspect #=> [1, 2, 3] 

fail_to_modify_object(the_object) 

the_object.object_id # => 14554660 
the_object.inspect #=> [1, 2, 3] 

翻動Array對象到一個新的Time的例子是人爲的,但你的想法。

是否可以將一個由任意數量的變量引用的對象變成另一個類的實例?

+0

閱讀這篇不錯的文章-http://robertheaton.com/2014/07/22/is-ruby-pass-by-reference-or-pass-by-value/並回答這個問題http:// stackoverflow .com/questions/1872110/is-ruby-by-reference-by-value –

回答

1

要修改保留其身份(對象ID)的對象,新對象必須至少屬於與以前相同的類;否則,這是沒有意義的。將一個Time實例修改爲Array實例是不可能的,反之亦然不可能保持其身份。

或者,如果你在你的第二個例子意味着簡單地改變the_objectTime實例的引用到Array實例,然後就是局部變量的作用域的問題,並沒有任何與不變性。

2

Bang方法並不總是需要修改對象。

邦只是一個約定,說這個版本的方法是「更危險」比沒有爆炸的人。例如,在rails中,許多爆炸方法引發異常,而不是返回nil

此外,方法沒有爆炸的事實並不意味着它不會修改對象(例如Array#pop)。

至於如何修改的對象不提供任何突變的方法 - 您可以使用Object#instance_variable_getObject#instance_variable_set

class X 
    attr_reader :foo 

    def initialize 
    @foo = :bar 
    end 
end 

x = X.new 
x.foo # => :bar 
x.instance_variable_set(:@foo, :baz) 
x.foo # => :baz 

但請注意,如果有人沒有給你直接訪問如果你正在嘗試做某件事,99.99%的時間你做錯了事情。

+0

酷;這可以用來以比其實現更多的方式修改對象。 我還是很想知道是否有可能以真正的任意方式改變對象,比如讓它們成爲一個完全不同的類的實例。 但是,如果可能的話,它應該和不應該使用的問題與問題無關。 –

1

您需要區分變量和對象。

在方法中,您可以訪問該對象。您無法訪問在方法外定義的變量。

如果您編寫object = Time.now,則不會更改該對象,而是將另一個對象指定給變量object。舊的對象仍然存在。 您的方法之外的變量仍保留舊對象。

您可以通過發送消息來更改對象。如果你有一個數組對象,你可以在這裏看到你的變量的方法:http://ruby-doc.org/core-2.2.0/Array.html一些方法改變了數組,有些方法只是返回一些東西。

你可以做一些事情,如。即使這是作爲對[]=的方法調用來實現的。它會改變你的數組對象的第一個元素到現在持有一個時間對象。所以你可以自由地改變你的數組對象。

如果你是高級的,你甚至可以添加新的方法到你的數組對象,以便它可以表現得像一個時間對象。但這幾乎總是不是一個好主意。

變量只存在於其定義的位置。

+0

問題不在於改變什麼對象超出範圍的變量引用,而是關於是否有可能以任意方式更改由任意數量的變量引用的對象(如將數組更改爲時間)這些變量。在原地更改對象的實例方法可以實現此目的,並且更改實例變量可以實現此目的,但是您在可更改的範圍內受到限制。 –

相關問題