在打开的单例类中调用单例类方法

Posted

技术标签:

【中文标题】在打开的单例类中调用单例类方法【英文标题】:Calling Singleton Class Methods Inside Open Singleton Class 【发布时间】:2020-01-01 18:19:38 【问题描述】:

我试图理解为什么我不能从开放类中调用单例类上定义的方法,但我可以从实际类中调用。

谁能解释为什么第一个例子失败而第二个例子没有?

class One
  class << self
    def one; end
    one
  end
end

NameError (undefined local variable or method 'one' for #<Class:One>)

class Two
  class << self
    def one; end
  end

  self.one
end

=> nil

【问题讨论】:

我认为(如果我错了,请有人纠正我)元类习语更像是模块扩展而不是继承模式,例如module One; def one; end; end 然后 class Two; extend One; end 在这种情况下 One 没有方法 one 但是通过扩展 Two 有。因此One.one #=&gt; NoMethodError 但是Two.one 工作正常 【参考方案1】:

你的例子比它需要的更令人困惑。它根本不需要单例类:

class Foo
  def bar; end

  bar # NameError
end

Foo.new.bar

在这里,我们有一个类Foo 和一个实例方法bar。单例类仍然只是一个类,所以这实际上与您的示例完全相同。

def 没有显式定义,定义了最接近的词法封闭类定义的实例方法,在本例中为 Foo。没有像bar 这样的显式接收者发送的消息将消息发送到self。在类定义体内,self 是类本身。

所以,def barFoo 中定义了一个实例方法,即您可以在Foo实例 上调用的方法。

类定义体内的barself发送消息,即Foo。由于Foo不是自身的实例,所以没有名为bar的方法,所以,方法调用失败。

这与单例类完全相同,因为它仍然只是一个类。

【讨论】:

【参考方案2】:

首先,您对方法所属的位置做出了错误的假设。从类上下文中调用实例方法one 应该不会成功。在您的第一个 sn-p 中,您尝试从 One 的单例类的单例类中调用方法 one(因为它是从 singleton_class 上下文中调用的)。

用普通类/实例方法举例说明:

class One
  def self.one()
    puts :class
  end
  def one
    puts :instance
  end
  one()
end
#⇒ class

因此,预期的行为将是提高NameError。现在答案很简单:它引发了NameError,因为这个方法不存在。

【讨论】:

以上是关于在打开的单例类中调用单例类方法的主要内容,如果未能解决你的问题,请参考以下文章

swift中的单例类变量? [复制]

单例类和元类

Ruby 中 BasicObject 的单例类的单例类

iOS中的单例

单例类的总结

在单例类构造函数中进行 Ajax 调用