それぞれの違いを簡単にまとめてみる。
メソッド | 呼び出し可能範囲 |
---|---|
public | クラス内外どこからでも呼び出し可能。 |
private | クラス、同じインスタンス内からのみ呼び出し可能。 |
protected | クラス、同じインスタンス内に**加え、**同じクラスの他のインスタンスからも呼び出し可能。 |
rubyのデフォルトが、publicで他の二つとの違いは、わかりやすいのですが、他の2つ(privateとprotected)の違いがよくわからなかったので調べてみました。
privateとprotectedの具体的な違いを調べてみた。
- private
privateメソッドを呼び出す時は、レシーバは指定できない。 - protected
protectedメソッドを呼び出す時は、レシーバは指定できる。
この呼び出し時にレシーバを指定できるかできないかの違いがこの2つを理解するポイントになります。
レシーバとは
レシーバーは特に Ruby の用語というわけではなく、オブジェクト指向一般に使われる用語です。
下記コードのrunメソッドを呼び出している、car1がレシーバーです。
class Car
def run
print run
end
end
car1=Car.new
car1.run #左側がレシーバー
参照:rubyのレシーバとは
具体的にprivateメソッドをコードで確認してみる
class Sample1
def s1_call_private
s1_private # 通常の呼び出し
end
def s1_call_private_with_receiver
self.s1_private # あえてレシーバ(self)を明示して指定
end
private
def s1_private
p "Welcome to my private room!"
end
end
s1 = Sample1.new
s1.s1_call_private
=> "Welcome to my private room!"
s1.s1_call_private_with_receiver
=> NoMethodError: private method `s1_private' called for..
引用:[Ruby] privateメソッドの本質とそれを理解するメリット
このように、privateメソッドは、呼び出し時にレシーバーを指定できないルールとなっています。
次に、protectedメソッドもコードで確認してみましょう。
具体的にprotectedメソッドをコードで確認してみる
class Sample2
def s2_call_protected
s2_protected # 通常の呼び出し
end
def s2_call_protected_with_receiver
self.s2_protected # あえてレシーバ(self)を明示して指定
end
protected
def s2_protected
p "Welcome to my protected room!"
end
end
s2 = Sample2.new
s2.s2_call_protected
=> "Welcome to my protected room!"
s2.s2_call_protected_with_receiver
=> "Welcome to my protected room!"
参照:[Ruby] privateメソッドの本質とそれを理解するメリット
このように、protectedメソッドは、呼び出し時にレシーバーを指定できます。
まとめ(public,private,protectedの使い分け)
- どのレベルでメソッドを外部から隠蔽したいのか
- 機能実装のために他のインスタンスを参照する必要があるのか
で使い分けをするのが良さそう。
-
他のクラスからもメソッドを使用したい場合は、publicメソッドを使う。
-
基本的にメソッドを定義したクラスやインスタンスでのみそのメソッドを使用したい場合は、privateメソッドを使う。
-
2項演算子の実装にその他のインスタンス(オブジェクト)の状態を参照する必要がある、もしくは、調べる必要があり、そのクラス内でのみメソッドを使用したい(他のクラスから隠蔽したい)場合は、protectedを使う。