【问题标题】:Dynamic class generation with attributes具有属性的动态类生成
【发布时间】:2015-04-25 12:44:56
【问题描述】:

我正在尝试生成一个动态类

dynamic_name = 'Person'
Object.const_set(dynamic_name, Class.new {def init(attrs); end}) 

我想为这个类生成属性。我试着这样做:

Person.class.module_eval { attr_accessor :name}

但是是否可以直接将其放入init 方法中?我还需要为属性设置约束,例如上面的属性名称应该是size > 0,并且允许包含正则表达式/^[A-Z]/的字符

【问题讨论】:

  • 你为什么要这样做?你想达到什么目标?
  • 我必须使用动态名称动态创建类,并且属性具有动态名称和类型!这不是实现的方法吗?
  • 什么是sizename 是什么?
  • 不管sizename,你的最后一段代码都是无效的。
  • 这不是代码,只是对约束的解释

标签: ruby metaprogramming


【解决方案1】:

attr_accessor :name 只不过是 DSL 又名语法糖,用于为 namename= 方法定义普通访问器。它可能没有任何约束。要定义约束,应该使用显式的 setter 定义:

attr_reader :name
def name= neu
  raise ArgumentError.new("Name must be not empty") if neu.empty?
  # additional constraints
  @name = neu
end

与上述问题无关的不同之处在于:

是否可以直接将其放入init 方法中?

虽然我仍然不明白所有这些woodoo 舞蹈的目的,但有可能:

def init *args
  # native init stuff
  self.class.define_method :name do
    @name
  end unless self.class.method_defined? :name
  self.class.define_method :name= do |neu|
    raise ArgumentError.new("Name must be not empty") if neu.empty?
    # additional constraints
    @name = neu
  end unless self.class.method_defined? :name=
end

希望对你有帮助。

【讨论】:

  • 当我使用下面的代码块时,我收到错误test.rb:12:in 'init': private method 'define_method' called for Person:Class (NoMethodError) from test.rb:36:in '<main>'
  • 哦,是的。它是私人的。将self.class.define_method(:name) 更改为self.class.send(:define_method, :name)
  • 哪一个?所有define_method 电话?
  • 好的,输入如何访问name 属性然后,当我这样做时test = Person.new.init 'xxx' puts test.name 我收到错误undefined method name' for :name:Symbol (NoMethodError) `
猜你喜欢
  • 2020-05-11
  • 1970-01-01
  • 2021-03-03
  • 1970-01-01
  • 1970-01-01
  • 2019-09-02
  • 2014-10-18
  • 2021-11-16
  • 1970-01-01
相关资源
最近更新 更多