【问题标题】:Attr_accessor on class variables类变量上的 attr_accessor
【发布时间】:2014-02-03 01:15:32
【问题描述】:

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

【问题讨论】:

  • attr_accessor 是 ruby​​ 在对象实例(以及实例变量)上创建 setter 和 getter 的简写,不适用于类级变量
  • 虽然我对 Rails 几乎一无所知,但我相信require 'active_support',你可以使用cattr_accessor :things

标签: ruby


【解决方案1】:

attr_accessor 定义实例的访问器方法。如果你想要类级别自动生成的访问器,你可以在元类上使用它

class Parent
  @things = []

  class << self
    attr_accessor :things
  end
end

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

但请注意,这会创建一个类级别的实例变量而不是一个类变量。无论如何,这可能是您想要的,因为类变量的行为与您在处理 w/ 继承时可能期望的不同。请参阅“Class and Instance Variables In Ruby”。

【讨论】:

  • 这仍然返回相同的错误。 class Parent @@things = [] class
  • 查看我的编辑 - 我在初始化中为您添加。由于它是类级别的实例 var 而不是类变量,因此您只需要使用一个 @
  • 如果我只想在课堂上使用@things 怎么办?例如实例变量我可以只使用attr_reader,但是对于类级别的实例变量我必须依靠attr_accessor 自己来写入它(假设它不是一个数组,而是像整数这样不可变的东西)。
【解决方案2】:

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

class Something
  class <<self
    attr_accessor :things
  end
end

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

【讨论】:

  • 在这种情况下,如果一个类继承了Something,那么继承的类对象的实例是否会获得新的东西副本,对吧?
  • @Talespin_Kit:正确 - 每个类都有自己的 @things 变量,因为实例变量特定于拥有它们的对象。
【解决方案3】:

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

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

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

【讨论】:

    【解决方案4】:

    这可能是最简单的方法了。

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

    【讨论】:

      【解决方案5】:

      还请注意,单例方法 是仅适用于单个对象的方法。在 Ruby 中,类也是一个对象,所以它也可以有单例方法!因此,请注意您何时可能会打电话给他们。

      例子:

      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

      【讨论】:

        【解决方案6】:
        Parent.class_variable_get(:@@things)
        

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

        【讨论】:

          【解决方案7】:
          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]
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2010-10-28
            • 1970-01-01
            • 1970-01-01
            • 2012-05-26
            • 1970-01-01
            • 2013-01-03
            • 1970-01-01
            • 2014-02-21
            相关资源
            最近更新 更多