与状态混合

Mixins with state

我正在研究 "Pickaxe Book" 并且作者给出了以下示例作为在不使用实例变量的情况下提供 module/mixin 状态的技术:

...the module could use a module-level hash, indexed by the current object ID, to store instance-specific data...

module Test
  State = {}
  def state=(value)
    State[object_id] = value
  end
  def state
    State[object_id]
  end
end

class Client
  include Test
end

c1 = Client.new
c2 = Client.new
c1.state = 'cat'
c2.state = 'dog'
c1.state # => "cat"
c2.state # => "dog"

我不清楚这是如何工作的。特别是 object_idobject_id 方法如何能够以这种方式访问​​ Client 实例?我尝试使用 length 来查看它是否会根据该索引进行索引,但我得到:

NameError: undefined local variable or method `length' for #<Client:0x00000000ecc570>

我想确保我理解这里发生的事情的原则。

如果Client包括Test,而c1是一个Client,那么object_id就是c1.object_id,继承自[=16] =].每个 Ruby 对象都保证是唯一的 object_id。并非所有对象都保证具有 length(此外,许多对象将具有非唯一长度,例如 "f"[8] 共享 length 1) .

How is the object_id method able to access the Client instance in this manner?

  1. state=()方法在包含时继承自Test模块。包含的模块创建一个匿名 class,插入继承链中包含 class 的正上方。

  2. 这一行:

    c1.state = 'cat'
    

    相当于:

    c1.state=('cat')
    

    而当 c1 调用 state=() 时,state=() 方法内部 self 将等于 c1。在def中,self等于调用该方法的对象。

  3. 当你调用没有接收者的方法时,self 是隐式接收者。里面 state=()

    def state=(value)
      State[object_id] = value
    end
    

    object_id() 方法在没有接收者的情况下被调用,因此 self 成为接收者。结果,行:

    State[object_id] = value
    

    相当于:

    State[self.object_id] = value
    

    相当于:

    State[c1.object_id] = value