2016-02-19 39 views
0

考慮下面的一組類:Ruby爲什麼要將變量改變到一個類的範圍之外?

class Cat 
    def initialize(value) 
    @value = value 
    end 

    def speak 
    @value.pop() 
    puts @value 
    end 
end 

speak = ["Meow","Hiss","Chirp"] 

cat = Cat.new(speak) 
cat.speak 
puts speak 

class Dog 
    def initialize(value) 
    @value = value 
    end 

    def speak 
    @value.sub!("Bark", "Woof") 
    puts @value 
    end 
end 

speak = "Bark!" 

dog = Dog.new(speak) 
dog.speak 
puts speak 

我希望下面的輸出是:

Meow 
Hiss 
Meow 
Hiss 
Chirp 
Woof! 
Bark! 

它是,如果我提供@value = value.dup,但給人的感覺並不Ruby'esque

但是,我收到的輸出是:

Meow 
Hiss 
Meow 
Hiss 
Woof! 
Woof! 

這是Ruby的預期行爲嗎?一個班是否應該修改參數創建者?我知道設置@value = value將返回相同的object_id的@valuevalue但是,如果我設置@value = 'somethingelse'不應該它創建一個新的對象,而不是更改原始對象?

+3

這是預期的行爲。在Ruby中,所有對象(除了像Fixnum這樣的基本類型)都通過引用傳遞。當傳遞給方法時,Ruby不會創建對象的副本。 –

+2

我最近剪了我的頭髮。現在,有些人認爲我是「Jörg」,有些人認爲我是「Mittag先生」。我的理髮師認識我爲「米塔格先生」。但是,儘管他只剪了「Mittag先生」的頭髮,認識我爲「Jörg」的人也觀察到我的頭髮被剪掉了。這跟你叫我的名字無關。有什麼相關的是我改變了。 –

回答

3

是的,這是預期的行爲。不,如果你想分配一個新的對象,那麼你需要顯式調用dupclone對象上:

@value = value.dup 

閱讀有關在Ruby文檔clone and dup之間的差異。

+3

是的,這是Ruby的一個重要原則之一:除非你可以正確承擔對它們的所有權,否則不要破壞你給出的東西。如果您需要對參數中傳入的內容進行修改,請複製一份。 – tadman