首页 > 解决方案 > 如何动态地为类创建 attr_reader

问题描述

如何动态地在对象上创建属性并将对象分配给它的值?我有以下代码:

class Component
  def initialize
  end    
end

class BaseClass
  def initialize
  end

  # define class methods
  def self.create_component(**args)
    # create attr_accessor with name "ball"
    # set ball = Component.new
  end
end

class ChildClass < BaseClass

  create_component :name => "ball"
  create_component :name => "baseball"
  def initialize
  end
end

我的目标是,当 ChildClass 调用“create_component”方法时,这应该使用 :name 参数中提供的名称创建一个属性,并将一个“组件”对象实例化到该属性。

object = ChildClass.new
object.ball #=> to return object reference (Component class 1)
object.baseball #=> to return object reference (Component class 2)

标签: ruby

解决方案


您可以像这样定义 BaseClass :

class Component; end

class BaseClass
  @@components = []
  def initialize
    @@components.each do |attr|
      instance_variable_set("@#{attr}", Component.new)
    end
  end
  def self.create_component(name:)
    attr_reader name.to_sym
    @@components << name
  end
end

class ChildClass < BaseClass
  create_component :name => "ball"
  create_component :name => "baseball"
end

object = ChildClass.new

object.ball
# => #<Component:0x00007fa62fbdf3f8>

object.baseball
# => #<Component:0x00007fa62fbdf3a8>

基本上你做三件事:

  1. @@components创建一个存储自定义attr_reader名称列表的类级实例变量
  2. 在内部create_component,调用attr_reader创建方法并将其添加到@@components列表中
  3. 在内部initialize,为每个设置初始值(如果您愿意,也可以使用参数@@components为这些自定义值)。initialize

推荐阅读