为什么实例变量可以通过带有<<运算符的字段阅读器进行修改?

Isa*_* To 1 ruby

考虑以下课程.

class Test
  attr_reader :word
  def initialize(word)
    @word = word
  end

  def append_word(token)
    word << token
  end
end
Run Code Online (Sandbox Code Playgroud)

考虑该类的示例用法.

2.4.0 :001 > t = Test.new('Hello')
 => #<Test:0x007f7f09902970 @word="Hello"> 
2.4.0 :002 > t.append_word(' world!')
 => "Hello world!" 
2.4.0 :003 > t.word
 => "Hello world!" 
2.4.0 :004 > 
Run Code Online (Sandbox Code Playgroud)

我是Ruby的新手.我不明白为什么我可以使用append_word实例方法来修改@wordTest实例的实例变量.word在append_word中似乎是一个字段读者.我的理解是,现场阅读器仅供阅读.如何才能word << tokenappend_word修改的值@word在测试实例?

Mar*_*iej 5

@word在内存中引用了一个对象.这个对象碰巧是一个Hello!字符串.您的类不允许(轻松地)为您的@word实例变量设置新对象,但目前没有任何内容阻止您直接修改对象.如果您希望对象不可修改,您可以.freeze:

class Test
  attr_reader :word
  def initialize(word)
    @word = word.freeze
  end

  def append_word(token)
    word << token
  end
end

> Test.new("Hello").append_word("world!")
# FrozenError (can't modify frozen String)
Run Code Online (Sandbox Code Playgroud)