Вот сложная часть, которую вам не хватает: переменная @b
не меняет в вашем примере.Он по-прежнему содержит тот же строковый объект, который вы изначально установили.Это сама строка , которая меняется.Это различие чрезвычайно важно, и если вы его не поймете, вы обнаружите, что ваша программа страдает от тысячи тонких ошибок.Вот оно:
Объекты и переменные - это две независимые вещи.Переменные похожи на слоты, а объекты - это то, что вы в них помещаете.Только оператор =
помещает новый объект в слот *;все остальное отправляет сообщения объекту в слоте.Когда вы пишете @thing = "hello"
, это помещает объект String "hello"
в слот @thing
.Когда вы пишете @thing << " world"
, вы не устанавливаете @thing
для содержания нового объекта;вы оставляете там тот же объект, но добавляете " world"
в конец строки, которую представляет объект.Это также означает, что любые другие слоты, содержащие тот же объект, также обнаружат, что их строки изменились!
Если вы хотите обойти это, вам придется использовать прокси-объект (чтобы получить сообщение <<
)как ormuriauga, описанный вместо непосредственного сохранения строки.Ruby's Delegator может быть полезен для этого.Хотя я бы посоветовал подумать, действительно ли вам это нужно, потому что это усложняет ваш дизайн, и часто есть лучший способ сделать это.
* ОК, это немного волнисто.Также есть специальный метод instance_variable_set
, который может устанавливать переменные экземпляра.Но не было бы никакого способа написать этот метод самостоятельно без использования операторов =
и eval()
.