单例对象上的attr_accessor未按预期工作

问题描述 投票:2回答:1

为什么Cat.new.name工作,但Dog.new.name不起作用,给出这两个不同的实现:

class Cat
end 

Cat.instance_eval do
  attr_accessor :name
end

但这不起作用:

class Dog
  class << self
    attr_accessor :name
  end
end

注意:我知道Dog.name可以工作,但我认为这两个实现都会导致为namename=的所有实例化创建DogCat方法。


问题背景:

首先:以下面的代码为例:

class Cat
end

Cat.instance_eval do
  attr_accessor :name
end

c = Cat.new
c.name = 'some cat name'
p c.name # => "some cat name"

关于ruby documentation of instance_eval,我会通过以下内容讨论instance_eval块:

  • 我们是在CatCatself)的背景下,所以从本质上讲,我们称之为Cat.attr_accessor :name,这是一个宏,它说“嘿,对于所有从Cat创建的实例,给他们方法namename=

我试图将这种理解扩展到以下,但它是错误的:

class Dog
  class << self
    attr_accessor :name
  end
end

d = Dog.new
d.name = "dog name" # => undefined method `name=' for #<Dog:0x007ff6c3062c20> (NoMethodError)

说说这个,我会说class << self说:

  • 把我放在Dog的单身对象的背景下,所以selfis现在Dog的单身对象
  • attr_accessor的单个对象上调用Dog宏(所以我们真的称之为<singleton_of_Dog>.attr_accessor :name)。现在每次我们实例化一个Dog对象时,每个狗对象现在都有namename=

错误显然表明我的想法不正确,但我不确定我错过了哪一部分。

我搜索过以前的堆栈溢出问题,阅读书籍和观看解释红宝石对象模型的视频。然而,显然有一些我尚未完全掌握的基本概念。

ruby
1个回答
1
投票

class << self的典型用法是创建一个块,其中实例方法被定义为类方法。这使您可以跳过在方法定义中键入self.,并使其他工具可用,如private / protected。

如何工作是通过打开Dog的单例类并向其添加实例方法。 Dog's singleton类的实例方法成为Dog的类方法。这只是单例类定义的一部分。

在attr_accessor的情况下,这是您在Dog的类范围内调用的方法,它定义了Dog上的实例方法。

当你在Dog的单例类上调用attr_accessor时,它会在Dog的singleton类上创建实例方法。 Dog's singleton类的实例方法成为Dog的类方法。这就是为什么你可以使用Dog.name =而不是Dog.new.name =和你的代码。

© www.soinside.com 2019 - 2024. All rights reserved.