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

标签 ruby

我有这段 Ruby 代码,我在其中尝试手动实现单例模式:

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

但我收到“为 A:Class (NoMethodError) 调用私有(private)方法‘new’”错误。这很令人费解,为什么我在第二个示例中出现此错误,而在第一个示例中却没有?唯一的区别是在第二个例子中 .new 是在类方法定义中调用的。我故意把 private_class_method 放在底部,这样就可以防止这种错误(把它放在顶部会给出两个例子的错误)。顺便说一句,我知道如果我将@a 从类实例变量更改为类变量(以@@ 开头),这将起作用。我不明白为什么这会起作用,因为我知道实例变量是相对于 SELF 的,而 SELF 是类,在我将 @a 初始化为 nil 的地方以及在 self.instance 中懒惰地实例化它的地方。

最佳答案

这是一件奇怪的事情。

A.new 不起作用,因为您应该只直接调用私有(private)方法,所以您应该使用显式 new 调用。

另一方面,new 调用类似于隐式 self.newself.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"

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

您不能将显式接收器与私有(private)方法一起使用

所以:Understanding private methods in Ruby

关于ruby - 为什么我只在类方法定义中收到 'private method new' 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26700691/

相关文章:

ruby - 在不丢失 Ruby 中的引号或注释的情况下加载和保存 YAML 文件

javascript - rails : has_many association through array of object IDs from form

ruby - 如何为一种方法编写 rspec 测试

反转正则表达式的 Rubyish 方式

ruby - 从文件中的数据构建 SQLite 数据库的最有效方法是什么?

ruby-on-rails - 挂起时如何调试 `rails s`?

Ruby,从UDP消息中获取传入地址

ruby-on-rails - Ruby - 将文件中的每一行读取到对象并将对象添加到数组

ruby-on-rails - 如何在 ruby​​ on rails 中创建向导表单

ruby-on-rails - 在我的两台计算机上同步 Rails 开发环境