【问题标题】:Why can I access private/protected methods using Object#send in Ruby?为什么我可以在 Ruby 中使用 Object#send 访问私有/受保护的方法?
【发布时间】:2011-01-31 22:13:21
【问题描述】:

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 }

.发送输出

foo
bar
zim
dib
fail

问题

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

也许更重要:

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

【问题讨论】:

标签: ruby language-design access-specifier


【解决方案1】:

技术上:因为send 不做任何事情来检查方法的可见性。 (这样做会比较麻烦。)

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

至于privateprotectedpublic是什么意思:

  • public 方法可以被任何发送者调用
  • protected 方法不能在方法类的实例或子类的实例之外调用
  • private 方法不能用显式接收器调用(有几个例外,例如 setter 方法,它总是必须有一个显式接收器,因此可以在类中以这种方式调用)

【讨论】:

  • 这很有道理,谢谢。您能否添加一些适当使用protectedprivate 的真实示例? :)
  • 好答案。值得指出的是,Ruby 1.9 引入了Kernel#public_send,它不会调用受保护/私有方法。它适用于 Ruby 1.8,带有 backports gem。
  • @smotchkkiss,这听起来完全是一个单独的问题。
猜你喜欢
  • 2014-10-31
  • 2011-01-06
  • 2012-01-09
  • 2018-12-10
  • 2018-10-21
  • 2011-12-05
  • 1970-01-01
  • 2019-02-13
相关资源
最近更新 更多