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

时间:2010-03-25 20:30:29

标签: 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

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

.send test

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

.send输出

foo
bar
zim
dib
fail

问题

标记为“测试输出”的部分是预期结果。那么为什么我只能通过Object#send访问私有/受保护的方法?

也许更重要:

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

1 个答案:

答案 0 :(得分:8)

技术上:因为send无法检查方法可见性。 (这样做会有更多的工作。)

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

至于privateprotectedpublic是什么意思:

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