为什么我可以使用Ruby中的Object#send访问私有/受保护的方法?

班级

class A

  private
  def foo
    puts :foo
  end

  public
  def bar
    puts :bar
  end

  private
  def zim
    puts :zim
  end

  protected
  def dib
    puts :dib
  end
end

A的实例

a = A.new

测试

a.foo rescue puts :fail
a.bar rescue puts :fail
a.zim rescue puts :fail
a.dib rescue puts :fail
a.gaz rescue puts :fail

测试输出

fail
bar
fail
fail
fail

.测试

[:foo, :bar, :zim, :dib, :gaz].each { |m| a.send(m) rescue puts :fail }

.send输出

foo
bar
zim
dib
fail

这个问题

标有“测试输出”的部分是预期结果.那么为什么我可以通过简单的Object#send来访问private / protected方法呢?

也许更重要的是:

Ruby中的public / private / protected有什么区别?什么时候使用?有人可以提供私人和受保护使用的真实世界示例吗?

最佳答案
从技术上讲:因为send不会检查方法可见性. (这样做会有更多的工作.)

哲学上:Ruby是一种非常宽松的语言.您已经可以打开一个课程并制作您想要公开的任何方法.语言设计者实现的发送方式允许它覆盖通常由私人强加的限制. Ruby 1.9最初将有两个变体,一个私有尊重发送和一个名为send!的不安全变体,但显然因为向后兼容性而被删除.

至于私人,受保护和公众意味着什么:

>任何发件人都可以调用公共方法
>不能在方法类的实例或子类的实例之外调用受保护的方法
>私有方法不能使用显式接收器调用(有一些例外,例如setter方法,它们总是必须有一个显式接收器,因此可以在类中调用)

转载注明原文:为什么我可以使用Ruby中的Object#send访问私有/受保护的方法? - 代码日志