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

mač*_*ček 5 ruby language-design access-specifier

班级

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
Run Code Online (Sandbox Code Playgroud)

A的实例

a = A.new
Run Code Online (Sandbox Code Playgroud)

测试

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
Run Code Online (Sandbox Code Playgroud)

测试输出

fail
bar
fail
fail
fail
Run Code Online (Sandbox Code Playgroud)

.测试

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

.send输出

foo
bar
zim
dib
fail
Run Code Online (Sandbox Code Playgroud)

这个问题

标有"测试输出"的部分是预期结果.那么为什么我可以简单地访问私有/受保护的方法Object#send

也许更重要的是:

public/ private/ protected在Ruby中有什么区别?什么时候使用?有人可以提供真实世界的例子privateprotected用法吗?

Chu*_*uck 8

技术上:因为send没有做任何事情来检查方法可见性.(这样做会有更多的工作.)

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

至于是什么private,protectedpublic指:

  • public 任何发件人都可以调用方法
  • protected 方法不能在方法类的实例或子类的实例之外调用
  • private 无法使用显式接收器调用方法(有一些例外,例如setter方法,它们总是必须有一个显式接收器,因此可以在类中调用)

  • 好答案.值得指出的是,Ruby 1.9引入了`Kernel#public_send`,它不会调用protected/private方法.它适用于带有`backports` gem的Ruby 1.8. (3认同)