Rubyにおけるメソッドの公開レベルには、public、protected、privateの3種類があります。それぞれメソッドへのアクセスを制御するために使いますが、特にprivateメソッドを指定する際にはいくつかの注意点があります。
- privateメソッドの基本的な性質
privateメソッドは、そのメソッドが定義されたオブジェクトの外部から呼び出すことができません。クラスのインスタンスメソッドの中でしか呼び出すことができず、レシーバ(オブジェクト)を指定することもできません。
class Example
def public_method
puts "This is a public method."
private_method
end
private
def private_method
puts "This is a private method."
end
end
e = Example.new
e.public_method # "This is a public method." "This is a private method."
e.private_method # エラー (NoMethodError)
public_method内でprivate_methodを呼び出すことはできますが、e.private_methodのように外部から直接呼び出すことはできません。
- レシーバを明示できない(selfを使えない)
privateメソッドを呼び出すとき、レシーバを明示することができません。self.private_methodのようにレシーバを明示して呼び出そうとすると、エラーが発生します。
class Example
def call_private_with_receiver
self.private_method # ここでエラーが発生します
end
private
def private_method
puts "This is a private method."
end
end
e = Example.new
e.call_private_with_receiver # エラー (NoMethodError)
これは、privateメソッドは現在のインスタンス(self)からしか呼び出すことができないためです。レシーバなしでprivate_methodと直接呼び出す必要があります。
- サブクラスでも呼び出せない
privateメソッドは、そのクラス内でのみ呼び出し可能であり、サブクラスでも直接呼び出すことができません。親クラスのprivateメソッドは、サブクラスで直接アクセスすることはできません。
class Parent
private
def private_method
puts "Private method in Parent"
end
end
class Child < Parent
def call_private
private_method # エラーは発生しないが、外部からは呼べない
end
end
child = Child.new
child.call_private # "Private method in Parent"
child.private_method # エラー (NoMethodError)
サブクラスから呼び出しているように見えますが、これはサブクラスが親クラスのコンテキストで動作しているためです。サブクラスが直接そのprivateメソッドにアクセスするわけではありません。
4. アクセス修飾子の書き方に注意
Rubyでは、privateアクセス修飾子を定義する場所に注意が必要です。private以下に書かれたメソッドはすべてprivateとなるため、意図しないメソッドがprivateにならないように注意する必要があります。
class Example
def public_method
puts "Public method"
end
private
def private_method
puts "Private method"
end
def another_private_method
puts "Another private method"
end
end
e = Example.new
e.public_method # "Public method"
e.private_method # エラー (NoMethodError)
e.another_private_method # エラー (NoMethodError)
privateの後に宣言したメソッドは全てprivateになります。もし特定のメソッドだけをprivateにしたい場合は、個別に明示することもできます。
class Example
def public_method
puts "Public method"
end
def another_public_method
puts "Another public method"
end
private :another_public_method
end
-
privateメソッドのユースケース
privateメソッドは、クラス内部での実装の詳細を隠蔽するために使います。外部に公開する必要のないメソッドや、クラスの内部処理をまとめるための補助的なメソッドをprivateにすることが一般的です。 -
例外:クラスメソッドの場合
privateメソッドはインスタンスメソッドに適用されますが、クラスメソッドをprivateにする場合はprivate_class_methodを使います。
class Example
def self.public_class_method
puts "Public class method"
end
private
def self.private_class_method
puts "Private class method"
end
end
Example.public_class_method # "Public class method"
Example.private_class_method # エラー (NoMethodError)
クラスメソッドのアクセス制御は、クラスメソッド専用の書き方が必要です。
まとめ
privateメソッドは、そのクラス内のみで使用でき、外部からのアクセスを防ぐための手段です。
レシーバを明示することはできないため、selfを付けて呼び出すことはできません。
privateメソッドはサブクラスからも直接呼び出すことができません。
privateの適用範囲に注意して、必要なメソッドだけがprivateになるように設計しましょう。
これらを理解して正しく使うことで、クラスの設計がより堅牢になります。