3

是否可以从字符串(方法名称)和块(方法的内容)在 ruby​​ 中定义实例方法?

我想这将需要使用 instance_eval(),但我还没有弄清楚如何混合这两种数据类型。字符串和块都是动态确定的,因此可以在开头使用“def #{string}”创建块 - 我不知道该怎么做。

我的用例是一个代表 Bacula 配置文件的类。配置文件可以有许多不同类型的资源。它们都存储在幕后相对复杂的数据结构中(由于其他原因,简化此结构不会完成我正在寻找的东西)。我希望通过命名方法快速访问资源。

例如,A 代表一个配置文件,B 代表另一个。A 有资源 Director、Client、Job,B 有 Messages 和 Director。

在这种情况下,A 应该有方法director()、client() 和job(),而B 有messages() 和director()。这些中的每一个都会从对象的相应配置文件中返回相关资源。

我知道有更简单的方法可以做到这一点(比如实现 [] 方法),但在这一点上,出于好奇,我正在寻求更难的解决方案。

4

1 回答 1

4

我认为您正在寻找的是define_methodModule 上的方法;但是,它是私有的,因此您必须使用class_eval或其他东西来运行它。

body = proc { self * 3 }
name = "triple"
c = Numeric

c.class_eval { define_method(name.to_sym, &body) }

3.triple # 9

还有一个带参数的方法:

body = proc { |second| [self * 3, second * 3] }
name = "triple_both"
c = Numeric

c.class_eval { define_method(name.to_sym, &body) }

puts 3.triple_both(5) # [9, 15]

将新方法放在单例对象(或 Eigenclass,或其他任何名称)上:

body = proc { puts @meme + @meme + @meme }
name = "meme"
class SwedishChef; def initialize; @meme = "bork"; end; end    
sc = SwedishChef.new
(class << sc; self; end).class_eval { 
  define_method(name.to_sym, &body)
}
sc.meme # borkborkbork

[编辑(Jörg W Mittag):我修复了单例方法示例。]

于 2009-07-10T15:54:08.203 回答