来自字符串和块的Ruby实例方法

时间:2009-07-10 15:49:36

标签: ruby instance

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

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

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

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

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

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

1 个答案:

答案 0 :(得分:4)

我认为您正在寻找的是模块上的方法define_method;但是,它是私有的,所以你必须使用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örgWMittag):我修复了单例方法示例。]