Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
731 views
in Technique[技术] by (71.8m points)

language design - Why does Ruby have both private and protected methods?

Before I read this article, I thought access control in Ruby worked like this:

  • 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

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?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

protected methods can be called by any instance of the defining class or its subclasses.

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 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.

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.

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...