为什么来自扩展模块的常量在用 self. 声明的类方法中不可用? [英] Why are constants from extended module not available in class methods declared with self.?

查看:33
本文介绍了为什么来自扩展模块的常量在用 self. 声明的类方法中不可用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为在 类中声明的方法之间没有区别 <<self 块和那些用 self. 前缀声明的块,但有:

I thought there were no differences between methods declared within a class << self block and those declared with a self. prefix, but there are:

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中不可用?

Why are constants of A available in m1 but not in m2?

推荐答案

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

In Ruby, constant lookup is not the same as method lookup. For method lookup, calling foo is always the same as calling self.foo (assuming it isn't private). Calling a constant FOO is very different from self::FOO or singleton_class::FOO.

使用非限定常量(例如 FOO)将在当前打开的模块中进行查找.一个模块用module Modclass Klassclass <<<;objmodule_eval 和变体.定义m1时,它们是B,然后是B.singleton_class.定义m2时,只打开B.

Using an unqualified constant (e.g. FOO) will do a lookup in the currently opened modules. A module is opened with module Mod, class Klass, class << obj, or module_eval and variants. When defining m1, these are B, and then B.singleton_class. When defining m2, only B is opened.

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

在这段代码中,Foo::Bar.hello 将返回 42,即使 X 不是 Bar 的常量,它的单例阶级或祖先.此外,如果您稍后将常量 X 添加到 Bar,则将返回该值.最后,以下定义是不等价的:

In this code, Foo::Bar.hello will return 42, even though X is not a constant of Bar, its singleton class or ancestor. Also, if you later add a constant X to Bar, then that value will be returned. Finally, the following definition is not equivalent:

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类,而在前面的例子中,FooFoo::Bar 打开的地方.

Indeed, when hello is defined, only the class Foo::Bar is opened, while in the previous example, both Foo and Foo::Bar where opened.

最后一个例子,显示显式作用域与继承的区别:

A last example, to show the difference an explicit scope can have with inheritance:

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

就您而言,您可能希望include您的模块,而不是extending,不是吗?

In your case, you probably want to include your module, instead of extending it, no?

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

Otherwise, you could use singleton_class::VAR, your code will work as you expect it.

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

这篇关于为什么来自扩展模块的常量在用 self. 声明的类方法中不可用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆