我有一个定义了常量的类。然后我定义了一个访问该类常量的类方法。这很好用。一个例子:
#! /usr/bin/env ruby
class NonInstantiableClass
Const = "hello, world!"
class << self
def shout_my_constant
puts Const.upcase
end
end
end
NonInstantiableClass.shout_my_constant
我的问题出现在尝试将此类方法移出到外部模块,如下所示:
#! /usr/bin/env ruby
module CommonMethods
def shout_my_constant
puts Const.upcase
end
end
class NonInstantiableClass
Const = "hello, world!"
class << self
include CommonMethods
end
end
NonInstantiableClass.shout_my_constant
Ruby将方法解释为从模块请求常量,而不是类:
line 5:in `shout_my_constant': uninitialized constant CommonMethods::Const (NameError)
那么,你的伙伴们有什么神奇的技巧让方法访问类不变?非常感谢。
答案 0 :(得分:16)
这似乎有效:
#! /usr/bin/env ruby
module CommonMethods
def shout_my_constant
puts self::Const.upcase
end
end
class NonInstantiableClass
Const = "hello, world!"
class << self
include CommonMethods
end
end
NonInstantiableClass.shout_my_constant
HTH
答案 1 :(得分:13)
值得注意的是,您不需要将模块包含在元类中。
class NonInstantiableClass
Const = "hello, world!"
class << self
include CommonMethods
end
end
Ruby有extend
关键字,可以有效地将模块接口添加到类中,例如
class NonInstantiableClass
Const = "hello, world!"
extend CommonMethods
end
您仍然需要确保使用self::Const
或const_get
引用正确的常量,但extend <module>
是将这些方法添加到类中的更好方法。
答案 2 :(得分:9)
问题是,如果您只是编写Const
,则会在模块创建时评估它。您必须使用Module#const_get
代替:const_get(:Const)
。执行该方法时,将在运行时对此进行评估。所以这发生在你的班级而不是你的模块中。