微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ruby – 为什么在使用self声明的类方法中,扩展模块的常量不可用.

我认为在类<<<自我阻挡和自我宣告的人.前缀,但有:
module A
  VAR = 'some_constant'
end

class B
  extend A

  class << self
    def m1
      puts VAR
    end
  end

  def self.m2
    puts VAR
  end
end

B.m1 # => OK
B.m2 # => uninitialized constant B::VAR

为什么A的常数可用于m1而不是m2?

解决方法

在Ruby中,常量查找与方法查找不同.对于方法查找,调用foo始终与调用self.foo相同(假设它不是私有的).调用常数FOO与self :: FOO或singleton_class :: FOO非常不同.

使用不合格的常数(例如FOO)将在当前打开的模块中进行查找.使用模块Mod,类Klass,类<< obj或module_eval和变体.当定义m1时,它们是B,然后是B.singleton_class.当定义m2时,只有B被打开.

module Foo
  X = 42
  class Bar
    def self.hello
      X
    end
  end
end

在这代码中,Foo :: Bar.hello将返回42,即使X不是Bar,它的单例类或祖先的常量.此外,如果您以后将一个常量X添加到Bar,那么该值将被返回.最后,以下定义不等同:

module Foo
  X = 42
end

class Foo::Bar
  def self.hello
    X
  end
end

Foo::Bar.hello # => uninitialized constant Foo::Bar::X

实际上,当定义了hello时,只有类Foo :: Bar被打开,而在前面的例子中,Foo和Foo :: Bar都打开了.

最后一个例子,显示一个明确的范围可以带有继承的差异:

class Base
  X = 42
  def self.foo
    X
  end
  def self.bar
    self::X
  end
end

class Parent < Base
  X = :other
end

Parent.foo # => 42
Parent.bar # => :other

在你的情况下,你可能想要包括你的模块,而不是扩展它,否?

否则,您可以使用singleton_class :: VAR,您的代码将按照您的期望工作.

module A
  VAR = 'some_constant'
end

class B
  extend A

  class << self
    def m1
      puts singleton_class::VAR # not necessary here,as singleton_class is opened
    end
  end

  def self.m2
    puts singleton_class::VAR # necessary here!
  end
end

B.m1 # => OK
B.m2 # => OK

原文地址:https://www.jb51.cc/ruby/273523.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐