Ruby重写<<方法

fl0*_*00r 0 ruby

我有 class A

class A
  attr_reader :b
  def b=param
    @b = param
    print "success"
  end
end

>> a = A.new
>> a.b = "hello world!"
#> "success"
#> "hello world!"
>> a.b << " and goodbye!"
#> "helo world! and goodbye!"
Run Code Online (Sandbox Code Playgroud)

我的"成功"在哪里?:)

我想打印'成功'每次我的变量都改变了.

我不能写

def b<<param
  @b << param
  print "success"
end
Run Code Online (Sandbox Code Playgroud)

Chu*_*uck 5

这是你缺少的棘手部分:变量在你的例子@b 中不会改变.它仍包含您最初设置的相同字符串对象.这是字符串本身正在发生变化.这种区别非常重要,如果你不掌握它,你会发现你的程序受到一千个微妙的错误的困扰.这里是:

对象和变量是两个独立的东西.变量就像插槽一样,对象就是你放入它们的东西.只有=操作员将新对象放入插槽*; 其他一切都会向插槽中的对象发送消息.写入@thing = "hello"时,将String对象"hello"放入插槽@thing.在编写时@thing << " world",您没有设置@thing包含新对象; 你要在那里留下相同的对象,但是添加" world"到对象所代表的字符串的末尾.这也意味着持有相同对象的任何其他插槽也会发现它们的字符串已更改!

如果你想解决这个问题,你将不得不使用代理对象(接收<<消息),如ormuriauga描述,而不是直接存储字符串.Ruby的Delegator可能对此有用.虽然我会建议考虑你是否真的需要这个,因为它确实使你的设计复杂化,并且通常有更好的方法来做到这一点.

好的,这有点手工波浪.还有instance_variable_set可以设置实例变量的特殊方法.但不会有任何的方式来写自己,方法不使用=运营商 eval().