为什么我可以在 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
.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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
从技术上讲:因为
send
不会执行任何操作来检查方法可见性。 (这样做会需要更多工作。)从哲学上来说:Ruby 是一种非常宽容的语言。您已经可以打开一个类并将任何您想要的方法公开。语言设计者实现
send
的方式允许它覆盖通常由private
施加的限制。 Ruby 1.9 最初有两个变体,一个private
尊重send
和一个名为send!
的不安全变体,但这显然被放弃了向后兼容性。至于
private
、protected
和public
的含义: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 byprivate
. Ruby 1.9 was originally going to have two variants, aprivate
-respectingsend
and an unsafe variant calledsend!
, but this was apparently dropped for backwards compatibility.As for what
private
,protected
andpublic
mean:public
methods can be called by any senderprotected
methods cannot be called outside of an instance of the method's class or an instance of a subclassprivate
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)