2016-02-19 6 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 для @value и value, однако если я установил @value = 'somethingelse', не должен ли он создать новый объект вместо изменения исходного объекта?

+3

Это ожидаемое поведение. В Ruby все объекты (кроме примитивов, таких как Fixnum) передаются по ссылке. Ruby не копирует объект, когда вы передаете его методу. –

+2

Недавно я отрезал себе волосы. Теперь некоторые люди знают меня как «Йорг», и некоторые люди знают меня как «Миттаг». Мой парикмахер знает меня как «Миттаг». Однако, хотя он только режет волосы г-на Миттага, люди, которые знают меня как «Йорг», также наблюдают, как мои волосы были вырезаны. Не важно, какое имя вы называете мне. Важно то, что * I * изменился. –

ответ

3

Да, это ожидаемое поведение. И нет, если вы хотите назначить новый объект, то вам необходимо явно вызвать dup или clone на объекте:

@value = value.dup 

Читайте о разнице между clone and dup в документации на Ruby.

+3

Да, это один из важных принципов Ruby: не подделывайте вещи, которые вам даны, если вы не можете правильно принять на себя ответственность за них. Если вам нужно внести изменения в что-то, переданное аргументом, сделайте копию. – tadman

Смежные вопросы