【问题标题】:Ruby instance methods from a string and a block来自字符串和块的 Ruby 实例方法
【发布时间】:2026-01-24 23:05:01
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

  • 您能否举个简单的例子说明您想在什么地方使用该方法,以及您打算如何使用它?

标签: ruby instance


【解决方案1】:

我认为您正在寻找的是模块上的方法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örg W Mittag):我修复了单例方法示例。]

【讨论】:

  • 这适用于类方法,但我特别需要实例方法。
  • 实例方法是什么意思?你的意思是你只希望它们出现在一个物体上?
  • 没错。用例已添加到我的原始帖子中。
  • 在 Jorg W Mittag 的编辑之后,单例类可以解决问题。谢谢!