Ruby 2.7 开始,私有方法 getter 可以显示指定 self 接收者(会和很多书上的描述打架),getter,setter 保持一致

Mark24 · June 24, 2020 · Last by Mark24 replied at June 25, 2020 · 2167 hits

本贴本来是个提问帖,我自己找到答案了。留下作为记录。


原帖内容:《Ruby 私有方法 getter 为什么可以显示指定接收者了?(和书上不一样)》

《Ruby 程序员修炼之道》、《Ruby 基础教程(第五版)》 都在强调,一旦方法被设置为 private,getter 是无法显示声明调用者的。

为什么我可以显示声明 self.egg, 它还能工作?书写错了?

代码如下:

class Baker
    def work
        puts "---work---"
        puts "--egg-getter--"
        self.egg
        puts "---set egg--"
        self.egg=555
        puts '--self.egg--'
        self.egg
        puts '---just egg--'
        egg
    end

    private
    def egg
        puts "--egg--getter--"
        @egg ||= 0
    end

    def egg=(value)
        puts "--setter--getter--"
        @egg = value
    end
end

运行

  ruby-test git:(master)  ruby -v
ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux]   # 我的ruby版本
  ruby-test git:(master)  irb -r './private.rb' --prompt simple
>> b=Baker.new
>> b.egg # private getter方法,直接调用会报错,正常
Traceback (most recent call last):
        3: from /home/mark24/.asdf/installs/ruby/2.7.1/bin/irb:23:in `load'
        2: from /home/mark24/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/irb-1.2.3/exe/irb:11:in `<top (required)>'
        1: from (irb):2
NoMethodError (private method `egg' called for #<Baker:0x000055c96a887898>)
>> b.egg=999  # private setter 方法,直接调用会报错,正常
Traceback (most recent call last):
        5: from /home/mark24/.asdf/installs/ruby/2.7.1/bin/irb:23:in `<main>'
        4: from /home/mark24/.asdf/installs/ruby/2.7.1/bin/irb:23:in `load'
        3: from /home/mark24/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/irb-1.2.3/exe/irb:11:in `<top (required)>'
        2: from (irb):2
        1: from (irb):3:in `rescue in irb_binding'
NoMethodError (private method `egg=' called for #<Baker:0x000055c96a887898>)
>> b.work  # public 方法,直接调用
---work---
--egg-getter--
--egg--getter--  # 这不对呀,应该报错才对呀
---set egg--
--setter--getter-- 
--self.egg-- 
--egg--getter--
---just egg--
--egg--getter--
=> 555
>> 

反过来想一想:如果 private 方法在 class 内部都不能调用,那什么时候允许调用?

Reply to coderliu

我就是不太明白这边。 通过实例,肯定是无法调用的。

在 class 内部,的其他方法里,调用 private 的 getter 方法。到底应不应该显示声明 self?

是 Ruby 更新了?

经过我的不懈努力终于找到了。

也就是所有书里面(过时了)

对于 Private 方法的 getter 不可以显示 self 调用,要改写了。

https://www.ruby-lang.org/en/news/2019/12/25/ruby-2-7-0-released/

Calling a private method with a literal self as the receiver is now allowed. 
[Feature #11297], [Feature #16123]

def foo
end
private :foo
self.foo
You need to Sign in before reply, if you don't have an account, please Sign up first.