微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ruby 访问修饰符,不同版本的不同输出 2.5 - 2.7

如何解决ruby 访问修饰符,不同版本的不同输出 2.5 - 2.7

我正在尝试运行此代码,它使用不同版本的 ruby​​ 2.5 - 2.7 提供不同的输出

代码

class ParentClass
    def the_public_method
        self.method1
    end

    private

    def method1
        puts "The private has been called"
    end
end

class ChildClass < ParentClass 
    def test
        self.method1
    end
end

ParentClass.new.the_public_method 
ChildClass.new.test

ruby 2.5 上它给出:

Traceback (most recent call last):
    1: from main.rb:19:in `<main>'
main.rb:3:in `the_public_method': private method `method1' called for 
#<ParentClass:0x000056367ee0b388> (NoMethodError)
Did you mean?  method
               methods
exit status 1

ruby 2.7 上它给出:

The private has been called
The private has been called

我认为旧版本的 ruby​​ 的第一个输出是正确的.. 有任何反馈吗?

解决方法

我认为旧版 ruby​​ 的第一个输出是正确的..有什么反馈吗?

两个输出都是正确的。 Ruby 2.7 中的规范发生了变化,因此 Ruby 2.7 的行为自然会有所不同。

最初,私有方法的规则是“私有方法只能在没有显式接收者的情况下被调用”。

然而,这意味着您不能使用私有 setter,因为 foo = :bar 是局部变量赋值,而 self.foo = :bar 是不允许的。

因此,规则更改为“只有在没有显式接收器的情况下才能调用私有方法,除了 setter,其中允许文字伪变量 self 作为接收器”。

但是,这仍然没有考虑到 self + 2self.foo += 2 之类的东西,其中 +foofoo= 是私有的,并且许多,许多其他极端情况。

有一段时间,Ruby 开发人员试图通过忽略其中一些极端情况或添加一组更复杂的异常来解决此问题,但实际上,解决方案相当简单:将规则更改为“私有方法”只能使用文字伪变量 self 作为显式或隐式接收器调用。

这是自 Ruby 2.7 以来的规则。

,

Ruby 2.7 allows calling a private method with self

在 Ruby 2.7 之前,允许使用文字 self 作为接收者调用私有写入/赋值方法,但使用 self 调用任何其他私有方法都会引发 NoMethodError 错误。

Ruby 2.7 旨在标准化自方法和私有方法之间的交互。上述不一致在 Ruby 2.7 中已修复。

所以第一个输出在 Ruby 2.7 之前是正确的,第二个输出在 Ruby 2.7 之后是正确的。

,

在 Ruby 中,private 方法仍然可以从继承的类访问,但用于要求非显式接收(即隐式调用,如 mehtod1 但不是 obj.method1 或 { {1}})

如@eux 所述,最后一项要求已放宽 in ruby 2.7,因此您现在也可以调用 self.method1


Ruby 可见性的另一个怪癖是它链接到实例而不是类本身。这解释了 self.method 的行为,让您了解以下代码:

private

此处发生 NoMethodError 是因为 class Foo def initialize(name) @name = name end def ==(rhs) name == rhs.name end private attr_reader :name end f = Foo.new("bar") f == f # NoMethodError 是私有的,因此您无法访问另一个对象的方法 attr_reader :name。要启用此行为,请使用 name

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。