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 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不起作用?
constant lookup searches for constants that are defined in
Module.nesting
,Module.nesting.first.ancestors
,andObject.ancestors
ifModule.nesting.first
is nil or a module
self在class_scope和eigen_scope中是相同的.
尽管如此,Module.nesting是不同的:
> [B]用于class_scope
> [#< Class:B>,B]用于eigen_scope
所以Module.nesting.first.ancestors是:
> class_scope的[B,A,Object,Kernel,BasicObject]
eigen_scope的[#< Class:B>,A :: ClassMethods,#< Class:Object>,#< Class:BasicObject>,Class,Module,BasicObject]
A没有被搜索,但是A :: ClassMethods!
所以你可以定义:
module A module ClassMethods NAME = 'Bob' end end
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。