はじめに
この記事を書いた動機は、Rubyにおけるメソッドのアクセス制御である、privateとprotectedの違いが分からなかったためです。
どちらもメソッドを隠し、クラス外から呼び出しができないようにする目的で使用されるそうですが、自分にはその二つの違いがよく分かっていませんでした。
この記事では、privateとprotectedの違いについて、簡単に説明します。
対象読者
最近、他言語からRubyに移ってきた方
privateとprotectedの違いについて知りたい方
なぜアクセス制限を行うのか
クラスを設計するときに、クラス内でしか参照されないようなメソッドを書く場合があります。
こことき、クラス内の他のメソッドから実行されるだけのメソッドが、クラス外から実行できるようになっていると予想外の結果になる可能性があります。
そのため、適宜メソッドにアクセス制限を行う必要があります。
Rubyメソッドにおけるアクセス制御の種類
クラス内で定義できるメソッドは、 public、private、protectedの三通りの呼び出し制御を持ちます。
Rubyリファレンスマニュアルには、
・public に設定されたメソッドは制限なしに呼び出せます。
・private に設定されたメソッドは関数形式でしか呼び出せません。
・protected に設定されたメソッドは、そのメソッドを持つオブジェクトが selfであるコンテキスト(メソッド定義式やinstance_eval)でのみ呼び出せます。
とあります。
しかし、この文章だけではよく分かりません。(少なくとも筆者は全然わかりませんでした)
public
特に呼び出し制御の指定がない場合、クラス内で定義したメソッドはpublicになります(デフォルトの呼び出し制御)。
publicに設定されているメソッドは、クラスの内外問わず自由に呼び出すことができます。
メソッドのデフォルトがpublicなので特に記述する必要はありませんが、
意図的に明示したい場合はpublicと記述すると、記述した行以降のメソッドがpublicになります。
class Hoge
public
def foobar
p "this is public method."
end
end
private, protected
呼び出し制限がないpublicとは異なり、定義したメソッドにprivateまたはprotectedを設定すると、クラス外からの呼び出しができなくなります。
private、protectedメソッドを呼び出したい場合には、呼び出すメソッドを別に同クラス内に定義しておき、呼び出しメソッドを通じて関数形式で実行することになります。
private
、protected
と記述すると、記述した行以降のメソッドはすべて指定した呼び出し制御が設定されます。
class Hoge
# 呼び出しメソッド
def foobar
foo
bar
end
private
def foo
p "this is private method."
end
protected
def bar
p "this is protected method."
end
end
hoge = Hoge.new
hoge.foobar # -> "this is private method."
# -> "this is protected method."
hoge.foo # -> NoMethodError
hoge.bar # -> NoMethodError
privateとprotectedの違い
ここまでは、privateとprotectedに違いがないように思えます。
しかし、privateは同じインスタンス内からしか呼び出せないのに対し、
protectedは同じクラスやサブクラスのインスタンスであれば、他のインスタンスからも呼び出せるというところに特徴があります。
また、privateはクラス内のレシーバ形式では呼び出せず、関数形式でしか呼び出すことができません。
class Hoge
def foobar
other_hoge = Hoge.new
other_hoge.bar # -> 成功
other_hoge.foo # -> 失敗
end
private
def foo
p "this is private method."
end
protected
def bar
p "this is protected method."
end
end
Hoge.new.foobar # -> "this is protected method."
# -> NoMethodError
まとめ
Rubyにおけるメソッドのアクセス制御には、public・private・protectedの3種類が存在する。
publicには呼び出し制限がない。
private、protectedには呼び出し制限がある。
privateは同じインスタンス内でのみ、他のメソッドから関数形式で呼び出すことができる。
protectedはprivateの特徴に加え、同じクラスやサブクラスのメソッドであれば他のインスタンスからでも呼び出せる。