如何使模块常量在特征类中也可见?
Posted
技术标签:
【中文标题】如何使模块常量在特征类中也可见?【英文标题】:How to make a module constant also visible within an eigenclass? 【发布时间】:2017-05-28 14:28:07 【问题描述】:我创建了一个包含常量NAME
和方法hello
的模块。如果一个类包含模块,则两个定义都应该在不同的范围内可见。
module A
NAME = 'Otto'
def self.included(base)
base.extend(ClassMethods)
end
def hello(name = 'world')
self.class.hello(name)
end
module ClassMethods
def hello(name = 'world')
"Hello #name!"
end
end
end
class B
include A
def instance_scope
p [__method__, hello(NAME)]
end
def self.class_scope
p [__method__, hello(NAME)]
end
class << self
def eigen_scope
p [__method__, hello(NAME)]
end
end
end
B.new.instance_scope
B.class_scope
B.eigen_scope
#=> script.rb:34:in `eigen_scope': uninitialized constant Class::NAME (NameError)
from script.rb:41
但该常量在特征类的实例方法范围内不可见,class << self
。
有没有办法让模块更健壮并在上述错误范围内提供常量?
【问题讨论】:
感谢您提出有趣的问题。我学到了一些新东西! @EricDuminil 一点也不!你的解释很有用。 【参考方案1】:解决方案
class << self
def eigen_scope
p [__method__, hello(self::NAME)]
#=> [:eigen_scope, "Hello Otto!"]
end
end
为什么self::NAME
有效?
A::NAME
将是最简单的硬编码版本。
B::NAME
也可以,因为 B
包括 A
在eigen_scope
内部,self
是B
,所以self::NAME
也可以工作
self::NAME
也适用于 self.class_scope
self::NAME
在 instance_scope
中不起作用:B
实例不是类/模块。
为什么NAME
不起作用?
Here 的解释很好。
常量查找搜索定义在
Module.nesting
、Module.nesting.first.ancestors
和Object.ancestors
如果Module.nesting.first
为 nil 或模块
self
在class_scope
和eigen_scope
中是相同的。
Module.nesting
不同:
[B]
为 class_scope
[#<Class:B>, B]
为eigen_scope
所以Module.nesting.first.ancestors
是:
[B, A, Object, Kernel, BasicObject]
为class_scope
[#<Class:B>, A::ClassMethods, #<Class:Object>, #<Class:BasicObject>, Class, Module, Object, Kernel, BasicObject]
为eigen_scope
A
未被搜索,但 A::ClassMethods
!
所以你可以定义:
module A
module ClassMethods
NAME = 'Bob'
end
end
【讨论】:
感谢您的解释。有没有办法调整模块,使hello_name(NAME)
也可以在特征类中工作?
对不起,我不明白这个问题。
任何想法为什么在这种情况下持续查找如此奇怪?在 class_scope 内它工作得很好,但self
在两种情况下都一样?以上是关于如何使模块常量在特征类中也可见?的主要内容,如果未能解决你的问题,请参考以下文章