如何使模块常量在特征类中也可见?

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 &lt;&lt; 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 包括 Aeigen_scope 内部,selfB,所以self::NAME 也可以工作 self::NAME 也适用于 self.class_scope self::NAMEinstance_scope 中不起作用:B 实例不是类/模块。

为什么NAME 不起作用?

Here 的解释很好。

常量查找搜索定义在 Module.nestingModule.nesting.first.ancestorsObject.ancestors 如果 Module.nesting.first 为 nil 或模块

selfclass_scopeeigen_scope 中是相同的。

Module.nesting 不同:

[B]class_scope [#&lt;Class:B&gt;, B]eigen_scope

所以Module.nesting.first.ancestors 是:

[B, A, Object, Kernel, BasicObject]class_scope [#&lt;Class:B&gt;, A::ClassMethods, #&lt;Class:Object&gt;, #&lt;Class:BasicObject&gt;, Class, Module, Object, Kernel, BasicObject]eigen_scope

A 未被搜索,但 A::ClassMethods!

所以你可以定义:

module A
  module ClassMethods
    NAME = 'Bob'
  end
end

【讨论】:

感谢您的解释。有没有办法调整模块,使hello_name(NAME) 也可以在特征类中工作? 对不起,我不明白这个问题。 任何想法为什么在这种情况下持续查找如此奇怪?在 class_scope 内它工作得很好,但self 在两种情况下都一样?

以上是关于如何使模块常量在特征类中也可见?的主要内容,如果未能解决你的问题,请参考以下文章

如何使一个类中的私有哈希图对其他类可见[关闭]

如何使屏幕背景数据快速可见?

定义仅在某个模块/类中可见的方法

特征可以具有具有私有和受保护可见性的属性和方法吗?特质可以有构造函数、析构函数和类常量吗?

您如何使基础架构代码仅在命名空间中可见?

vb中符号常量的作用范围是啥?