Rubyのメソッド可視性をマスター!public/protected/privateの違いと設計指針
生徒
「Rubyでメソッドを作っていると、たまに外部から呼び出せないエラーが出ます。これって何が原因なんですか?」
先生
「それは『メソッドの可視性(かしせい)』の設定が関係しているかもしれません。メソッドには、誰でも使えるものと、自分専用のものがあるんですよ。」
生徒
「自分専用のメソッドがあるんですね!使い分けるメリットは何ですか?」
先生
「プログラムの安全性を高めるために非常に重要です。public、protected、privateという三つのキーワードについて、基本から順番に解説していきますね!」
1. メソッドの可視性とは?
Rubyのプログラムにおいて、メソッドは「特定の処理をまとめた命令」のことです。このメソッドに対して、「どこから呼び出すことができるか」という制限をかける仕組みをメソッドの可視性(かしせい)と呼びます。例えば、家電製品をイメージしてください。誰でも触れる「電源ボタン」は公開されていますが、製品の内部にある「制御回路のスイッチ」は、修理業者や内部の部品しか触れないようになっています。プログラミングも同じで、すべての処理を公開してしまうと、思わぬところでデータが書き換えられたり、間違った使い方がされたりしてバグの原因になります。適切に隠すことで、壊れにくい安全なプログラムを作ることができるのです。
Rubyの文法を基礎からしっかり固めたい人や、 現場で役立つ「テスト駆動開発」の考え方まで身につけたい人には、 評価の高いこの一冊がおすすめです。
プロを目指す人のためのRuby入門をAmazonで見る※ Amazon広告リンク
2. 誰でも呼び出せるpublicメソッド
public(パブリック)は、その名の通り「公開」されている状態です。特に何も指定せずにメソッドを作ると、基本的にはこのpublicになります。クラスの外側からでも、他のプログラムからでも、自由に使ってもらうための窓口としての役割を果たします。例えば、銀行のATMでいえば「お金を引き出す」「残高を確認する」といった、利用者が直接操作できる機能がこれにあたります。初心者のうちはほとんどのメソッドをpublicで作ることが多いですが、何でも公開しすぎると、後でプログラムを修正するときに「どこで使われているか分からない」という状態になり、修正が大変になることもあります。
class Robot
# デフォルトでは public になります
def say_hello
puts "こんにちは!私はロボットです。"
end
end
robot = Robot.new
# クラスの外側から呼び出すことができます
robot.say_hello
こんにちは!私はロボットです。
3. 自分専用の秘密の処理privateメソッド
private(プライベート)は、そのクラスの中だけでしか使えない「非公開」のメソッドです。クラスの外側から robot.secret_method のように呼び出そうとすると、エラーが発生して止まってしまいます。これは、クラス内部の複雑な計算や、外に見せる必要のない下準備のための処理によく使われます。例えば、料理のレシピをメソッドにする場合、「材料を切る」のは外から指示できますが、「心臓の鼓動を調整する」ような、生き物の根本的な仕組みは外部から勝手にいじられては困りますよね。このように、外部に公開するインターフェース(操作窓口)を絞り込むことで、プログラムの使い勝手を良くすることができます。
class CoffeeMachine
def make_coffee
# 内部でこっそり秘密の処理を呼ぶ
boil_water
puts "コーヒーが完成しました!"
end
private
def boil_water
puts "お湯を沸かしています..."
end
end
machine = CoffeeMachine.new
machine.make_coffee
# machine.boil_water と書くとエラーになります
お湯を沸かしています...
コーヒーが完成しました!
4. 仲間内だけで共有するprotectedメソッド
protected(プロテクテッド)は、publicとprivateの中間のような性質を持っています。同じクラスの中、あるいはそのクラスを継承した(特徴を引き継いだ)子どものクラスから呼び出すことができます。最大の特徴は、同じ種類のオブジェクト同士であれば、お互いのメソッドを呼び出せるという点です。例えば、二人の「人間」がいたとき、自分の「貯金額」は他人には教えたくありません(private)が、銀行員同士が「顧客のデータを照合する」という処理なら、同じ仲間(オブジェクト)同士で見せ合ってもいい、という場面で使われます。実務ではprivateに比べると使う機会は少ないですが、特殊な比較処理などで活躍します。
class User
attr_reader :name
def initialize(name, weight)
@name = name
@weight = weight
end
# 他のユーザーと比較するメソッド
def heavier_than?(other_user)
# 相手が同じ User クラスなら protected メソッドを呼べる
@weight > other_user.secret_weight
end
protected
def secret_weight
@weight
end
end
tanaka = User.new("田中", 70)
sato = User.new("佐藤", 65)
puts "#{tanaka.name}さんは#{sato.name}さんより重い?: #{tanaka.heavier_than?(sato)}"
田中さんは佐藤さんより重い?: true
5. カプセル化でプログラムを守る
ここまで紹介した可視性の使い分けは、プログラミングの世界でカプセル化と呼ばれます。これは、大切なデータや複雑な仕組みを「カプセル」の中に閉じ込めて、外からは決められたボタンだけを押させるようにする考え方です。カプセル化を徹底すると、もし内部の仕組みを改良しても、外からの使い方は変わらないため、他の部分に影響を与えずにプログラムをアップデートできます。パソコンを触ったことがない方にとって「隠す」というのは不便に感じるかもしれませんが、実は「間違った操作をさせないための優しさ」なのです。この設計思想を意識するだけで、あなたの書くRubyのコードは一気にプロっぽくなります。
6. 可視性を切り替える書き方のルール
Rubyで可視性を設定するには、メソッド定義の途中に private や protected と書くだけです。その一行を書いた後のメソッドはすべて、その指定された可視性になります。再び public と書けば、そこからはまた公開メソッドに戻ります。一般的には、クラスの上のほうに重要な公開メソッド(public)をまとめ、下のほうに private と書いてから補助的なメソッドを並べるのが、読みやすいコードの書き方とされています。また、Ruby 3以降では private def method_name のように、一行で特定のメソッドだけを指定する書き方もできるようになり、より柔軟に設計ができるようになりました。
7. いつprivateを使うべきか?設計の指針
初心者が迷うのは「どのメソッドをprivateにするべきか」という点です。基本的な指針は、「迷ったら、まずはprivateにする」ことです。一度publicとして公開してしまうと、他の誰かがそのメソッドを使い始めてしまうかもしれません。そうなると、後で名前を変えたくなったときに困ります。逆に、最初は自分専用(private)にしておいて、どうしても外から使いたくなったときにpublicに変えるのは簡単です。クラスの責任を最小限に抑え、外部とのやり取りをシンプルに保つことが、メンテナンスしやすいプログラムを作る最大の秘訣です。この「最小公開の原則」を覚えておきましょう。
8. 継承と可視性の関係に注意しよう
Rubyの大きな特徴として、親クラスのメソッドを子クラスが引き継ぐ「継承(けいしょう)」があります。親クラスで private に設定されたメソッドは、実は子クラスの中でも呼び出すことができます。これは他のプログラミング言語(Javaなど)とは少し異なる挙動なので、注意が必要です。Rubyの private は「レシーバ(呼び出す対象)を明示して呼び出すことができない」というルールに基づいています。そのため、自分自身のメソッドとして呼び出す分には、親から引き継いだ秘密のメソッドも使えるのです。この柔軟さがRubyの魅力ですが、意図せず親の秘密を暴きすぎないよう、設計時には注意しましょう。
class Parent
private
def secret_tip
puts "親から伝授された秘伝のコツ"
end
end
class Child < Parent
def practice
# 親の private メソッドも呼べる
secret_tip
end
end
child = Child.new
child.practice
親から伝授された秘伝のコツ