【问题标题】: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 工作正常

标签: ruby metaprogramming metaclass


【解决方案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,因为这个方法不存在。

    【讨论】:

      猜你喜欢
      • 2011-10-21
      • 2012-10-22
      • 1970-01-01
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      • 2011-03-26
      • 1970-01-01
      相关资源
      最近更新 更多