KaQiita

新米エンジニアが適当なことを書いてます。温かく見守ってやってください。

【Ruby】メソッドの可視性(public・protected・private の使い分け)について

はじめに

ふと「あれ、protected メソッドって何だっけ?」と思ったので、Ruby において public メソッドや private メソッドと何が違うのか、どう使い分けるのか、という観点でまとめてみようと思います。

public・protected・private

まずは public メソッド・protected メソッド・private メソッドについて簡単に違いをまとめてみます。

  • public メソッド:クラスの外部からでも自由に呼び出せるメソッド
  • protected メソッド:自クラスとサブクラスの内部かつレシーバ付きで呼び出せるメソッド
  • private メソッド:自クラスとサブクラスの内部かつレシーバ無しで呼び出せるメソッド

上記のような違いがあります。

このような「メソッドが public なのか、protected なのか、private なのか」を「メソッドの可視性」と言ったりします。

メソッドの可視性の選択基準

public・protected・private には上記のような違いがあるので、メソッドの可視性は以下のように選択します。

メソッドの可視性の選択基準

サンプルコード

以下の Dog クラスの greeting メソッドはクラスの外部で呼び出すので public にする必要があります。

class Dog
  def greeting
    'bow-wow!'
  end
end

dog = Dog.new
p dog.greeting #=> "bow-wow!"

一方で、以下の name メソッドは Dog クラスの外部で呼び出さず、レシーバ付きで呼び出す必要もないので private にすべきです。

class Dog
  def greeting
    'bow-wow!'
  end

  private

  def name
    'Pochi'
  end
end

dog = Dog.new
p dog.greeting #=> "Pochi : bow-wow!"

最後に一番ややこしい protected のサンプルコードを見ていきます。

以下の age メソッドは Dog クラスの外部で呼び出さず、レシーバ付きで呼び出す必要があるので protected にすべきです。

class Dog
  def initialize(name, age)
    @name = name
    @age = age
  end

  def older_than?(another_dog)
    another_dog.age < @age ? true : false
  end

  protected

  def age
    @age
  end
end

pochi = Dog.new('Pochi', 3)
shiro = Dog.new("Shiro", 5)

p pochi.older_than?(shiro) #=> false

Appendix:Matz の protected メソッドに対する見解

Ruby の protected メソッドについて調べる中で、Matz の protected メソッドに対する見解を見つけたので、Appendix として載せておきます。

Rubyメーリングリストのやりとりです。

まつもと ゆきひろです

(中略)

ruby の protected は self がそのメソッドを定義したクラス(またはモジュール)またはそのサブクラスである場所からしか呼べません.こちらはレシーバを指定した形式でも呼び出せます.

つまり,private は自分からしか見えないメソッドであるのに対して,protected は一般の人からは見られたくないが,仲間(クラスが同じオブジェクト)からは見えるメソッドです.

protected は例えば2項演算子の実装にもう一方のオブジェクトの状態を知る必要があるか調べる必要があるが,そのメソッドを public にして,広く公開するのは避けたいというような時に使います.

終わりに

Ruby におけるメソッドの可視性についてのまとめでした。

少しでも参考にしていただけると幸いです。

参考文献