我正在用 Ruby (1.9.3) 编写一小段代码,我使用了一对简单的“类枚举”类,它们用const_set定义了一些常量以及这些常量的一些行为(例如Days类可能有常量MON,TUE ... 和Days::MON.succ应该评估为TUE)。
我对这些课程非常满意。然而,在增加我的代码时,我有时需要添加更多,我不喜欢有五个或更多类共享 99% 的源代码的想法,例如:
class Days
NAMES = %w( MON TUE ... )
INSTANCES = []
def initialize(num)
@num = num
end
# An example operation
def +(n)
INSTANCES[(@num + n) % INSTANCES.length]
end
# Another example operation
def succ
self + 1
end
def to_s
NAMES[@num]
end
NAMES.each_with_index do |name, idx|
instance = new(idx)
INSTANCES[idx] = instance
const_set name, instance
end
end
class Months
NAMES = %w( JAN FEB ... )
...
end
我想知道是否可以使用 Ruby 的元编程功能来生成这些类。但是,我很难创建NAMES、INSTANCES和“枚举命名”常量(例如MON、TUE、...)。作为const_set的类方法Class,在这段代码中,它的上下文(self的值)分别是Days和Months。
在创建工厂方法时,我不得不这样做:
def enum_new(names_array)
Class.new do
const_set "NAMES" []
names_array.each_with_index do |name, idx|
NAMES[idx] = name
end
...
end
end
Days = enum_new(%w| MON TUE ... |)
Months = enum_new(%w| JAN FEB ... |)
但这不起作用(至少,不像我希望的那样),因为const_set不会在名称被神奇设置的类的上下文中调用(即Days和Months),但显然是在Class的上下文中; 因此,不仅不能从实例方法访问它,而且每次使用新的名称数组作为参数调用enum_new时,它都会被覆盖。使用类变量时会出现类似的问题,因为它们将在使用该方法生成的任何类之间共享(因为它们将成为Class的类变量,我猜)。
有没有办法在使用Class.new生成的类中创建常量,以这种方式获得与原始Days和Months类相同的类,而不必用几乎相同的类污染我的代码?
感谢您的关注和耐心!:)