在Ruby中列出attr_accessors的最快/一线方式?

Lan*_*ard 31 ruby introspection

列出所有定义方法的最短,单行方式是attr_accessor什么?我想这样做,如果我有一个类MyBaseClass,任何扩展它的东西,我可以attr_accessor在子类中定义.像这样的东西:

class MyBaseClass < Hash
  def attributes
    # ??
  end
end

class SubClass < MyBaseClass
  attr_accessor :id, :title, :body
end

puts SubClass.new.attributes.inspect #=> [id, title, body]
Run Code Online (Sandbox Code Playgroud)

如何显示attr_readerattr_writer定义?

duk*_*ave 43

提取的属性在一个数组,将它们分配到一个恒定,那么图示它们到attr_accessor.

class SubClass < MyBaseClass
  ATTRS = [:id, :title, :body]
  attr_accessor(*ATTRS)
end
Run Code Online (Sandbox Code Playgroud)

现在您可以通过常量访问它们:

puts SubClass.ATTRS #=> [:id, :title, :body]
Run Code Online (Sandbox Code Playgroud)

  • 难道不是`SubClass :: ATTRS`?您的语法建议将`ATTRS`消息发送到`SubClass`类型的实例 (2认同)

sep*_*p2k 39

没有办法(单行或其他)列出attr_accessor定义的所有方法,只列出attr_accessor定义的方法而不定义自己的attr_accessor.

这是一个覆盖MyBaseClass中的attr_accessor的解决方案,用于记住使用attr_accessor创建的方法:

class MyBaseClass
  def self.attr_accessor(*vars)
    @attributes ||= []
    @attributes.concat vars
    super(*vars)
  end

  def self.attributes
    @attributes
  end

  def attributes
    self.class.attributes
  end
end

class SubClass < MyBaseClass
  attr_accessor :id, :title, :body
end

SubClass.new.attributes.inspect #=> [:id, :title, :body]
Run Code Online (Sandbox Code Playgroud)

  • 轻微的挑剔,但在第5行,你不需要调用`super(*vars)`,因为你传递的方法与方法接收的相同; 你可以在没有任何参数或括号的情况下调用`super`,它会自动传递`*vars`. (4认同)
  • 默认情况下,超级传递参数(和阻止,如果有的话)背后的基本原理是通常接口不会改变,因此它就是你想要的.我会说拥抱Ruby并让其他人也接受它,即使这意味着他们必须知道super与super()不一样...... (3认同)
  • @MarkRushakoff:我想这是怎么回事。许多人认为“ super”和“ super()”是一回事(老实说,我不确定我是否会更喜欢它)。 (2认同)

Chr*_*lze 6

继承人使用mixin而不是继承:

module TrackAttributes
  def attr_readers
    self.class.instance_variable_get('@attr_readers')
  end

  def attr_writers
    self.class.instance_variable_get('@attr_writers')
  end

  def attr_accessors
    self.class.instance_variable_get('@attr_accessors')
  end

  def self.included(klass)
    klass.send :define_singleton_method, :attr_reader, ->(*params) do
      @attr_readers ||= []
      @attr_readers.concat params
      super(*params)
    end

    klass.send :define_singleton_method, :attr_writer, ->(*params) do
      @attr_writers ||= []
      @attr_writers.concat params
      super(*params)
    end

    klass.send :define_singleton_method, :attr_accessor, ->(*params) do
      @attr_accessors ||= []
      @attr_accessors.concat params
      super(*params)
    end
  end
end

class MyClass
  include TrackAttributes

  attr_accessor :id, :title, :body
end

MyClass.new.attr_accessors #=> [:id, :title, :body]
Run Code Online (Sandbox Code Playgroud)