为什么 Ruby 有私有方法和受保护方法?
在我阅读之前 这篇文章,我认为 Ruby 中的访问控制是这样工作的:
Before I read this article, I thought access control in Ruby worked like this:
-
public
- 可以被任何对象访问(例如Obj.new.public_method
) -
protected
- 只能从对象本身以及任何子类内部访问 -
private
- 与 protected 相同,但该方法不存在于子类中
-
public
- can be accessed by any object (e.g.Obj.new.public_method
) -
protected
- can only be accessed from within the object itself, as well as any subclasses -
private
- same as protected, but the method doesn't exist in subclasses
然而,看起来 protected
和 private
的行为是一样的,除了你不能使用 private
方法调用显式接收器(即 self.protected_method
有效,但 self.private_method
无效).
However, it appears that protected
and private
act the same, except for the fact that you can't call private
methods with an explicit receiver (i.e. self.protected_method
works, but self.private_method
doesn't).
这有什么意义?什么情况下您不希望使用显式接收器调用您的方法?
What's the point of this? When is there a scenario when you wouldn't want your method called with an explicit receiver?
protected
方法可以被定义类或其子类的任何实例调用.
protected
methods can be called by any instance of the defining class or its subclasses.
private
方法只能从调用对象内部调用.您不能直接访问另一个实例的私有方法.
private
methods can be called only from within the calling object. You cannot access another instance's private methods directly.
这是一个快速的实际示例:
Here is a quick practical example:
def compare_to(x)
self.some_method <=> x.some_method
end
some_method
在这里不能是 private
.它必须是 protected
因为你需要它来支持显式接收器.您典型的内部辅助方法通常可以是 private
,因为它们永远不需要像这样调用.
some_method
cannot be private
here. It must be protected
because you need it to support explicit receivers. Your typical internal helper methods can usually be private
since they never need to be called like this.
需要注意的是,这与 Java 或 C++ 的工作方式不同.Ruby 中的 private
类似于 Java/C++ 中的 protected
,因为子类可以访问该方法.在 Ruby 中,无法像 Java 中的 private
那样限制从其子类访问方法.
It is important to note that this is different from the way Java or C++ works. private
in Ruby is similar to protected
in Java/C++ in that subclasses have access to the method. In Ruby, there is no way to restrict access to a method from its subclasses like you can with private
in Java.
无论如何,Ruby 中的可见性在很大程度上是一种推荐",因为您始终可以使用 send
访问方法:
Visibility in Ruby is largely a "recommendation" anyways since you can always gain access to a method using send
:
irb(main):001:0> class A
irb(main):002:1> private
irb(main):003:1> def not_so_private_method
irb(main):004:2> puts "Hello World"
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> foo = A.new
=> #<A:0x31688f>
irb(main):009:0> foo.send :not_so_private_method
Hello World
=> nil