Ruby 为什么我会得到';私有方法新&x27;仅在类方法定义内出错
我有一段Ruby代码,尝试手动实现Singleton模式:Ruby 为什么我会得到';私有方法新&x27;仅在类方法定义内出错,ruby,Ruby,我有一段Ruby代码,尝试手动实现Singleton模式: class A @a = A.new def self.instance p 'initialized' @a end private_class_method :new end A.instance #=> prints 'initialized' 不幸的是,该对象将在调用.instance之前创建。为了避免这种情况,我考虑更改代码: class A @a = nil def s
class A
@a = A.new
def self.instance
p 'initialized'
@a
end
private_class_method :new
end
A.instance #=> prints 'initialized'
不幸的是,该对象将在调用.instance之前创建。为了避免这种情况,我考虑更改代码:
class A
@a = nil
def self.instance
p 'initialized'
@a ||= A.new
end
private_class_method :new
end
A.instance
但我得到了“为:Class(NoMethodError)调用私有方法'new'的错误”。这是非常令人费解的,为什么我在第二个例子中得到这个错误,而不是在第一个例子中?唯一的区别是在第二个示例中,在类方法定义中调用.new。我故意将private_class_方法放在底部,这样可以防止这种错误(将它放在顶部会给出两个示例的错误)。顺便说一句,我知道如果我将@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"
附言:
不能将显式接收器与私有方法一起使用
所以:你不需要
@a=nil
。没有它,@a=@a | | a.new
(扩展@a | |=a.new
)右侧的@a
是未定义的,因此将被评估为nil
@CarySwovelanda.new
和new
的行为将不同A.new
将引发异常,而new
不会。问题是,self.new
的行为应该像new
(隐式相同),但事实并非如此!调查原因是的,在你评论之前我注意到了,这就是为什么我删除了我的评论。(我认为使用显式接收者调用私有方法总是会引发异常,这是有意义的,因为它可能是从类外执行的。)我建议您编辑,将您的解释添加到您的答案中。@CarySwoveland,是的,但是Ruby中的new
在语义上与self.new
相同。但看起来方法调度并不这么认为。@CarySwoveland,你实际上是对的。matterI认为Ruby不会将私有方法发送给显式接收方吗。当它看到接收者是明确的,我想它会对自己说,“如果在向其发送privatenew
时,该接收器是self
,则可以;否则我就不干了。我可以添加一些代码来检查代码执行时是否存在这种情况,但在这种情况下,只要求编码人员不要使用显式接收器会更有效。”