在Ruby中动态定义命名类 [英] Dynamically define named classes in Ruby

查看:131
本文介绍了在Ruby中动态定义命名类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用Ruby编写内部DSL.为此,我需要以编程方式创建命名类和嵌套类.最好的方法是什么?我确认有两种方法可以做到这一点:

I am writing an internal DSL in Ruby. For this, I need to programmatically create named classes and nested classes. What is the best way to do so? I recon that there are two ways to do so:

  1. 使用Class.new创建一个匿名类,然后使用define_method向其中添加方法,最后调用const_set将它们作为命名常量添加到某个名称空间.
  2. 使用某种eval
  1. Use Class.new to create an anonymous class, then use define_method to add methods to it, and finally call const_set to add them as named constants to some namespace.
  2. Use some sort of eval

我已经测试了第一种方法并且它可以工作,但是对于Ruby来说,它是陌生的,我不确定将类作为常量是正确的方法.

I've tested the first way and it worked, but being new to Ruby, I am not sure that putting classes as constants is the right way.

还有其他更好的方法吗?如果不是,那么以上哪个更可取?

Are there other, better ways? If not, which of the above is preferable?

推荐答案

如果要创建具有动态名称的类,则几乎必须完全按照您说的做.但是,您不需要使用define_method.您只需将一个块传递给Class.new,即可在其中初始化该类.这在语义上与class/end的内容相同.

If you want to create a class with a dynamic name, you'll have to do almost exactly what you said. However, you do not need to use define_method. You can just pass a block to Class.new in which you initialize the class. This is semantically identical to the contents of class/end.

请记住const_set,以谨慎对待该范围内的接收者(self).如果要全局定义类,则需要在TopLevel模块上调用const_set(Ruby的名称和详细信息有所不同).

Remember with const_set, to be conscientious of the receiver (self) in that scope. If you want the class defined globally you will need to call const_set on the TopLevel module (which varies in name and detail by Ruby).

a_new_class = Class.new(Object) do
  attr_accessor :x

  def initialize(x)
    print #{self.class} initialized with #{x}"
    @x = x
  end
end

SomeModule.const_set("ClassName", a_new_class)

c = ClassName.new(10)

...

这篇关于在Ruby中动态定义命名类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆