为什么我只在类方法定义中得到'private method new'错误

时间:2014-11-02 15:01:07

标签: ruby

我有这个Ruby代码,我尝试手动实现Singleton模式:

class A
  @a = A.new

  def self.instance
    p 'initialized'
    @a
  end

  private_class_method :new
end

A.instance #=> prints 'initialized'

不幸的是,该对象将在A.instance被调用之前创建。为了避免这种情况,我想到了改变代码:

class A
  @a = nil

  def self.instance
    p 'initialized'
    @a ||= A.new
  end

  private_class_method :new
end

A.instance

我得到"私人方法`new'要求A:Class(NoMethodError)"但错误。这非常令人费解,为什么我在第二个例子中得到这个错误而不是第一个?唯一的区别是在第二个例子中.new在类方法定义中被调用。我故意将private_class_method放在底部,以防止出现这种错误(将它置于顶部会给出两个示例的错误)。顺便说一句,我知道如果我将@a从类实例变量更改为类变量(以@@开头),这将有效。我不明白为什么这会起作用,因为我知道实例变量是相对于SELF而SELF是类,我将@a初始化为nil,以及我在self.instance中实例化它的位置。

1 个答案:

答案 0 :(得分:1)

这是一件奇怪的事情。

A.new不起作用,因为您应该直接调用私有方法,因此您应该使用显式new调用。

另一方面,new调用类似于隐式self.new,但self.new会引发类似A.new的异常。这是我不理解的奇怪部分

class A
  def self.instance
    p 'initialized'
    # ok
    new
    # should be ok but it is not
    self.new rescue p("error self.new: #{$!}")
    # should fail
    A.new rescue p("error A.new: #{$!}")
  end

  private_class_method :new
end

A.instance
# "initialized"
# "error self.new: private method `new' called for A:Class"
# "error A.new: private method `new' called for A:Class"

PS:http://weblog.jamisbuck.org/2007/2/23/method-visibility-in-ruby

您不能将隐式接收器与私有方法一起使用

SO:Understanding private methods in Ruby