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

发布于 2024-08-26 05:37:56 字数 925 浏览 13 评论 0原文

的类实例

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 测试

[: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 之间有什么区别?何时分别使用?有人可以提供私有受保护使用的真实示例吗?

The class

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

instance of A

a = A.new

test

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

test output

fail
bar
fail
fail
fail

.send test

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

.send output

foo
bar
zim
dib
fail

The question

The section labeled "Test Output" is the expected result. So why can I access private/protected method by simply Object#send?

Perhaps more important:

What is the difference between public/private/protected in Ruby? When to use each? Can someone provide real world examples for private and protected usage?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

云巢 2024-09-02 05:37:56

从技术上讲:因为 send 不会执行任何操作来检查方法可见性。 (这样做会需要更多工作。)

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

至于 privateprotectedpublic 的含义:

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

Technically: Because send doesn't do anything to check method visibility. (It would be more work to do so.)

Philosophically: Ruby is a very permissive language. You can already just open up a class and make any method you want public. The language designers implemented send in a way that allows it to override the restrictions normally imposed by private. Ruby 1.9 was originally going to have two variants, a private-respecting send and an unsafe variant called send!, but this was apparently dropped for backwards compatibility.

As for what private, protected and public mean:

  • public methods can be called by any sender
  • protected methods cannot be called outside of an instance of the method's class or an instance of a subclass
  • private methods cannot be called with an explicit receiver (with a couple of exceptions, such as setter methods, which always have to have an explicit receiver, and so can be called within the class that way)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文