了解Ruby中的私有方法

Ern*_*est 49 ruby access-specifier

class Example
 private
 def example_test
  puts 'Hello'
 end
end

e = Example.new
e.example_test
Run Code Online (Sandbox Code Playgroud)

这当然是行不通的,因为我们指定了Example(e)的显式接收器 - 实例,这是针对"私有规则"的.

但我无法理解,为什么人们不能在Ruby中做到这一点:

class Foo
 def public_m
  self.private_m # <=
 end
 private
 def private_m
  puts 'Hello'
 end
end

Foo.new.public_m
Run Code Online (Sandbox Code Playgroud)

public_m方法定义(即self)中的当前对象是Foo的实例.那么为什么不允许呢?为了解决这个问题,我必须self.private_m改为公正private_m.但为什么这个不同,是不是selfFoo里面的一个例子public_m?谁是裸字private_m呼叫的接收者?不是self- 实际上你省略了什么,因为Ruby会为你做这件事(会在self上调用private_m)吗?

我希望我没有太多混淆,我对Ruby仍然很新鲜.


编辑:谢谢你的所有答案.把它们放在一起我能(最终)神交明显的(而不是一个人,谁从来没有见过的东西,比如Ruby那么明显):这self本身可以是显性和隐性的接收器,并且赚取差价.因此,有两条规则,如果你要调用一个私有方法:self必须是隐式接收器,以及自我必须是当前类的一个实例(Example在这种情况下-而且,只有当自己好像里面实例方法的定义,在此期间发生方法执行).如果我错了,请纠正我.

class Example 

 # self as an explicit receiver (will throw an error)
 def explicit 
  self.some_private_method
 end

 # self as an implicit receiver (will be ok)
 def implicit
  some_private_method
 end

 private

 def some_private_method; end
end

Example.new.implicit
Run Code Online (Sandbox Code Playgroud)

消息的人谁可以在谷歌步道发现这样一个问题:这可能是有益的- http://weblog.jamisbuck.org/2007/2/23/method-visibility-in-ruby

小智 52

这是短期和长期的.Ruby中私有意味着一个方法不能使用显式接收器调用,例如some_instance.private_method(value).因此,即使隐式接收器是self,在您的示例中,您明确使用self,因此无法访问私有方法.

可以这样想一想,您是否希望能够使用已分配给类实例的变量来调用私有方法?不.自我是一个变量,所以它必须遵循相同的规则.但是,当您只调用实例中的方法时,它会按预期工作,因为您没有明确声明接收器.

Ruby实际上可以使用instance_eval调用私有方法:

class Foo
  private
  def bar(value)
    puts "value = #{value}"
  end
end

f = Foo.new
begin
  f.bar("This won't work")
rescue Exception=>e
  puts "That didn't work: #{e}"
end
f.instance_eval{ bar("But this does") }
Run Code Online (Sandbox Code Playgroud)

希望更清楚一点.

- 编辑 -

我假设你知道这会起作用:

class Foo
 def public_m
  private_m # Removed self.
 end
 private
 def private_m
  puts 'Hello'
 end
end

Foo.new.public_m
Run Code Online (Sandbox Code Playgroud)

  • 由于您引用了第512节,我希望您知道,根据允许侵权通知的相同小节,此类通知必须交付给相关业务的指定代理商.AFAIK,在Stack Overflow上编辑答案不是法律规定的追索权.Stack Overflow在其法律页面上包含有用的指南和完整的联系信息.(CYA注意:此评论仅限于信息价值,不应被视为法律建议.) (4认同)

Jör*_*tag 17

定义private在红宝石"只能被称为没有明确的接收器".这就是为什么你只能在没有显式接收器的情况下调用私有方法.没有其他解释.

请注意,规则实际上有一个例外:由于局部变量和方法调用之间存在歧义,以下内容将始终解析为对局部变量的赋值:

foo = :bar
Run Code Online (Sandbox Code Playgroud)

那么,如果你想打电话给作家,你会怎么做foo=?好吧,你必须添加一个显式的接收器,因为没有接收器Ruby就不会知道你想要调用方法foo=而不是分配给局部变量foo:

self.foo = :bar
Run Code Online (Sandbox Code Playgroud)

但是如果你想给一个private叫做作家打电话foo=怎么办?你不能self.foo =因为foo=private因而无法使用显式接收器调用.嗯,实际上对于这个特定情况(此情况),您实际上可以使用显式接收器self来调用编写器private.


The*_*heo 14

这很奇怪,但Ruby的可见性修饰符很多东西都很奇怪.即使self是隐式接收器,实际拼写它也会使它在Ruby运行时的眼睛中显而易见.当它说私有方法不能用显式接收器调用时,这意味着什么,甚至是self重要的.