Ruby模块,带有来自includer类的静态方法调用 [英] Ruby module with a static method call from includer class
问题描述
我需要在模块中定义使用包含此模块的类中的方法的常量:
I need to define the constant in the module that use the method from the class that includes this module:
module B
def self.included(base)
class << base
CONST = self.find
end
end
end
class A
def self.find
"AAA"
end
include B
end
puts A::CONST
但编译器会在第4行给出错误。
But the compiler gives the error on the 4th line.
还有其他方法可以定义常量吗?
Is there any other way to define the constant?
推荐答案
在Ruby中实现这一目标的更为惯用的方法是:
The more idiomatic way to achieve this in Ruby is:
module B
def self.included(klass)
klass.class_eval <<-ruby_eval
CONST = find
ruby_eval
# note that the block form of class_eval won't work
# because you can't assign a constant inside a method
end
end
class A
def self.find
"AAA"
end
include B
end
puts A::CONST
你在做什么(class<< base)实际上会让你进入A的元类的上下文
,而不是A本身。 find
方法是在A本身,而不是它的元类。要记住的是,类本身就是对象,因此有自己的元类。
What you were doing (class << base) actually puts you into the context of A's metaclass
, not A itself. The find
method is on A itself, not its metaclass. The thing to keep in mind is that classes are themselves objects, and so have their own metaclasses.
试图让它更清晰:
class Human
def parent
# this method is on the Human class and available
# to all instances of Human.
end
class << self
def build
# this method is on the Human metaclass, and
# available to its instance, Human itself.
end
# the "self" here is Human's metaclass, so build
# cannot be called.
end
def self.build
# exactly the same as the above
end
build # the "self" here is Human itself, so build can
# be called
end
不确定是否有帮助,但是如果你不理解它,你仍然可以使用上面的class_eval成语。
Not sure if that helps, but if you don't understand it, you can still use the class_eval idiom above.
这篇关于Ruby模块,带有来自includer类的静态方法调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!