类变量的Attr_accessor

时间:2014-01-14 19:52:57

标签: ruby

attr_accessor不适用于以下代码。错误显示“undefined method 'things' for Parent:Class (NoMethodError)”:

class Parent
  @@things = []
  attr_accessor :things
end
Parent.things << :car

p Parent.things

但是以下代码可以使用

class Parent
  @@things = []
  def self.things
    @@things
  end
  def things
    @@things
  end
end
Parent.things << :car

p Parent.things

7 个答案:

答案 0 :(得分:83)

attr_accessor定义实例的访问器方法。如果您想要类级自动生成的访问器,可以在元类

上使用它
class Parent
  @things = []

  class << self
    attr_accessor :things
  end
end

Parent.things #=> []
Parent.things << :car
Parent.things #=> [:car]

但请注意,这会创建一个类级实例变量而不是一个类变量。这很可能是你想要的,因为类变量的行为与你在处理w / inheritence时可能会有的不同。请参阅“Class and Instance Variables In Ruby”。

答案 1 :(得分:14)

attr_accessor实例变量生成访问器。 Ruby中的类变量是一个非常不同的东西,它们通常不是你想要的。你可能想要的是一个类实例变量。您可以将attr_accessor与类实例变量一起使用,如下所示:

class Something
  class <<self
    attr_accessor :things
  end
end

然后你可以写Something.things = 12,它会起作用。

答案 2 :(得分:3)

只是澄清一下:使用attr_accessor无法访问类变量。这都是关于实例变量的:

class SomeClass
  class << self
    attr_accessor :things
  end
  @things = []
end

因为在Ruby中,class是类“Class”的实例(上帝,我喜欢这样说),attr_accessor为实例变量设置访问器方法。

答案 3 :(得分:3)

这可能是最简单的方法。

class Parent
  def self.things
    @@things ||= []
  end
end
Parent.things << :car

p Parent.things

答案 4 :(得分:1)

请注意,单例方法是仅适用于单个对象的方法。在Ruby中,Class也是一个对象,所以它也可以有单例方法!所以要注意你什么时候打电话给他们。

示例:

class SomeClass
  class << self
    def test
    end
  end
end

test_obj = SomeClass.new

def test_obj.test_2
end

class << test_obj
  def test_3
  end
end

puts "Singleton methods of SomeClass"
puts SomeClass.singleton_methods
puts '------------------------------------------'
puts "Singleton methods of test_obj"
puts test_obj.singleton_methods

SomeClass的单​​例方法

<强> 测试

test_obj的单例方法

<强> test_2

<强> test_3

答案 5 :(得分:0)

Parent.class_variable_get(:@@things)

那将是内置方式。我认为在大多数情况下,这应该足够了。实例中不需要类变量访问器。

答案 6 :(得分:0)

class Parent
  @things = []
  
  singleton_class.send(:attr_accessor, :things)
end

当您动态定义访问器或在方法中创建访问器时,此模式最有用:

class Foo
  def self.add_accessor(name)
    singleton_class.send(:attr_accessor, name)
  end
end

Foo.add_accessor :things
Foo.things = [:car]
Foo.things # => [:car]