调用initialize方法时出现错误:
# typed: true
class A
extend T::Sig
sig {params(x: Integer).void}
private def initialize(x)
end
end
def main
A.new(91)
end以下是冰沙的结果:
editor.rb:11: Non-private call to private method initialize on A https://srb.help/7031
11 | A.new(91)
^^^^^^^^^
editor.rb:6: Defined in A here
6 | private def initialize(x)
^^^^^^^^^^^^^^^^^
Errors: 1[https://sorbet.run/#%23%20typed%3A%20true%0Aclass%20A%0A%20%20extend%20T%3A%3ASig%[…]0A%20%20end%0Aend%0A%0Adef%20main%0A%20%20A.new(91)%20%20%0Aend](https://sorbet.run/#%23%20typed%3A%20true%0Aclass%20A%0A%20%20extend%20T%3A%3ASig%%5B%E2%80%A6%5D0A%20%20end%0Aend%0A%0Adef%20main%0A%20%20A.new(91%29%20%20%0Aend)
发布于 2020-12-22 21:36:07
这看起来像是private中的一个错误,因为该语言对initialize进行了特殊处理,因此在默认情况下,它始终是bug。换句话说,您的代码与没有private的相同代码是100%相同的
# typed: true
class A
extend T::Sig
sig {params(x: Integer).void}
def initialize(x)
end
end
def main
A.new(91)
end
p A.private_instance_methods(false).include?(:initialize)
#=> trueWhich passes type checking with flying colors.
我的猜测是,索贝特并不“知道”initialize在Ruby中的特殊处理,因此将其视为一种正常的方法。我的第二个猜测是,索贝特包含了一个对Class#new的定义,如下所示:
class Class
def new(...)
obj = allocate
obj.initialize(...)
obj
end
end这意味着,只要initialize认为它是public,一切都是白兰地,但是一旦它认为它是private,它就失败了。
然而,Class#new的实际实现看起来更像这样:
class Class
def new(...)
obj = allocate
obj.__send__(:initialize, ...)
obj
end
end如果我的假设是正确的,那么在冰沙中有两个bug通常会相互抵消:
Class#new的定义是错误的。这意味着你总是会得到一个错误,因为initialize总是private,除了initialize的默认可见性也是错误的。然而,我没有检查这些假设,所以我可能完全错了。
https://stackoverflow.com/questions/65409434
复制相似问题