Ruby中的类变量的Getter / Setter

时间:2015-01-02 10:49:47

标签: ruby

可以为类变量自动生成/启用getter / setter,就像使用attr_accessor为实例变量生成的那样:

class School
  @@syllabus = :cbse

  def self.syllabus
    @@syllabus
  end

  def self.syllabus=(_)
    @@syllabus = _
  end
end

School.syllabus = :icse
School.syllabus # => :icse

2 个答案:

答案 0 :(得分:4)

您需要做的就是在类的范围内声明attr_accessor

class School
 class << self
   attr_accessor :syllabus
  end
end

School.syllabus = :icse
School.syllabus # => :icse

请注意,虽然底层成员不会<{1}}(这些变量没有内置解决方案)但是类范围内有@@syllabus,无论如何都是推荐的方法,请参阅this博客文章,了解两者之间的差异:

  

类变量的问题是继承。假设我想用Triangle子类化Polygon,如下所示:

@syllabus
     

什?但是Polygon的两侧是10?设置类变量时,可以为超类和所有子类设置它。

答案 1 :(得分:2)

Uri Agassi的答案是在类本身上设置实例变量,类似于类变量,但与类变量不同。有关差异的解释,请参见Difference between class variables and class instance variables?

你正在寻找的东西就像铁轨&#39; cattr_accessor。您可以通过一些元编程实现这一目标

module CattrAccessors
  def cattr_accessor(*attrs)
    cattr_reader(*attrs)
    cattr_writer(*attrs)
  end

  def cattr_reader(*attrs)
    attrs.each do |attr|
      define_singleton_method(attr) { class_variable_get("@@#{attr}") }
    end
  end

  def cattr_writer(*attrs)
    attrs.each do |attr|
      define_singleton_method("#{attr}=") { |value| class_variable_set("@@#{attr}", value) }
    end
  end
end

然后像这样使用它:

class School
  extend CattrAccessors

  attr_accessor :syllabus
end

我还没有测试过上面的模块,所以它可能无法正常工作。如果没有,请告诉我。