我有这个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
不过,我得到了"为A:Class(NoMethodError)调用的私有方法`new'"错误。这非常令人费解,为什么我在第二个例子中出现了这个错误,而在第一个例子中却没有?唯一的区别是在第二个例子中,在类方法定义中调用了.new。我故意把private_class_method放在底部,这样就可以防止这种错误(把它放在顶部会给出两个例子的错误)。顺便说一句,我知道如果我把@a从类实例变量改为类变量(以@@开头),这会起作用。我不明白为什么这会起作用,因为我知道实例变量是相对于SELF的,而SELF是类,在这里我将@a初始化为nil,在那里我在SELF.instance中懒惰地实例化它。
这里有一件奇怪的事情。
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:了解Ruby 中的私有方法