protected メソッドって何?

Ruby/Rails 勉強会@関西 の初級者向けレッスンで、public メソッドと private メソッドが紹介されて「protected は使うべきでない」とだけ紹介された。

グループワーク中に質問されたけど、時間がなくて答えられなかったのでメモ。

public
レシーバを指定して呼び出す。公開されたインターフェイス
private
レシーバを指定できない。自クラスの中だけで使える。非公開。

では protected とは、

protected
レシーバを指定できる。しかし非公開。
class Foo
  def initialize; @foo = 0 end
  def inspect; "Foo: #{@foo}" end

  def increment(o) o._increment end

  protected

  def _increment; @foo += 1 end
end

f = Foo.new         # => Foo: 0
g = Foo.new         # => Foo: 0

# f の public メソッドから g の protected メソッドを呼び出す
f.increment(g)
f                   # => Foo: 0
g                   # => Foo: 1

# 外部からは呼び出せない
g._increment
# ~> -:21:in `<main>': protected method `_increment' called for Foo: 1:Foo (NoMethodError)

class Bar
  def increment(o) o._increment end
end

b = Bar.new

# 他のクラスからは呼び出せない
b.increment(g)
# ~> -:24:in `increment': protected method `_increment' called for Foo: 1:Foo (NoMethodError)