[转]Method visibility in Ruby

From:[url]http://weblog.jamisbuck.org/2007/2/23/method-visibility-in-ruby[/url]
A common point of confusion to even experienced Ruby programmers is the visibility of public, protected, and private methods in Ruby classes. This largely stems from the fact that the behavior of those keywords in Ruby is different from what you might have learned from Java and C.

To demonstrate these differences, let’s set up a little script:


class Foo
def a; end

# call 'a' with explicit 'self' as receiver
def b; self.a; end

# call 'a' with implicit 'self' as receiver
def c; a; end
end

def safe_send(receiver, method, message)
# can't use 'send' because it bypasses visibility rules
eval "receiver.#{method}"
rescue => e
puts "#{message}: #{e}"
else
puts "#{message}: succeeded"
end

visibility = ARGV.shift || "public"
Foo.send(visibility, :a)

foo = Foo.new
safe_send(foo, :a, "explicit receiver ")
safe_send(foo, :b, "explicit 'self' receiver")
safe_send(foo, :c, "implicit 'self' receiver")

Basically, the script just creates a class “Foo” with three methods: a, which we’ll invoke directly with an explicit, non-self receiver; b, which invokes a with self as receiver, and c, which invokes a with an implicit receiver of self. We’ll use the safe_send method to call each of those methods and log the result.

So, first: the public keyword. In Ruby, public means that the method may be invoked just about any way you please; in technical terms, the receiver of the message may be either explicit (“foo.bar”), self (“self.bar”) or implicit (“bar”).

[quote]$ ruby demo.rb public
explicit receiver : succeeded
explicit 'self' receiver: succeeded
implicit 'self' receiver: succeeded[/quote]
The protected keyword puts a straitjacket around the method. Any method declared protected may only be called if the receiver is self, explicitly or implicitly. (Update: protected methods may actually be called any time the receiver is of the same class as ‘self’...and an explicit self as receiver is just a specific case of that. Modifying the script to demonstrate this condition is left as an exercise for the reader.)

[quote]$ ruby demo.rb protected
explicit receiver : protected method `a' called for #<Foo:0x3fc18>
explicit 'self' receiver: succeeded
implicit 'self' receiver: succeeded[/quote]
Lastly, the private keyword is the tightest setting of all. A private method cannot be called with an explicit receiver at all, even if that receiver is “self”.

[quote]$ ruby demo.rb private
explicit receiver : private method `a' called for #<Foo:0x3fc18>
explicit 'self' receiver: private method `a' called for #<Foo:0x3fc18>
implicit 'self' receiver: succeeded[/quote]
Note that, unlike languages such as Java, inheritance plays absolutely no part in determining method visibility in Ruby. Subclasses can access both protected and private methods of the superclass without trouble, so long as they abide by the rules laid out above.

The difference between protected and private is very subtle, as you can see, which explains why protected is rarely used by most Rubyists. If it is used at all, it is generally as a convention, to document methods that are internal to the class, but which lie closer to the public interface than others. In Rails, for instance, you might declare your controller filter methods and model validation methods as “protected” (because the framework will call those methods) and reserve the “private” designation for those methods that are only ever called from within your own model or controller code.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值