【Ruby入門】private と protected の使い方まとめ【メソッドのアクセス制御】

クラスの中で定義できるメソッドは、外から直接 呼び出せないようにアクセス制御を設定することができます。

以下から Ruby のアクセス制御で用いる「private」や「protected」の使い方を解説していきます。

 

アクセス制御の種類

Ruby では、それぞれのメソッドに呼び出し制限を設定することができ、以下の種類があります。

public よく使う 制限なし(デフォルトではこの設定になっている)。
private よく使う クラスの外からは呼び出せない。同じインスタンス内でのみ、関数形式で呼び出せる。
protected クラスの外からは呼び出せない。同じインスタンス内で呼び出せる。また、他のインスタンスでも同じクラスやサブクラスであれば呼び出せる。

 

以下から それぞれの使い方について、実際のプログラムを例に解説していきます。

 

アクセス制御の指定方法

はじめにアクセス制御の指定方法を紹介していきます。

publicprivateprotected をクラス内で書くと、それ以降のメソッドはすべて指定した呼び出し制限が設定されます。

 

以下は「morning」と「evening」メソッドに private、「night」メソッドに protected を設定する例。

class User
  def hello
    p "こんにちは"
  end

  private

  def morning
    p "おはよう"
  end

  def evening
    p "こんばんは"
  end

  protected

  def night
    p "おやすみ"
  end
end
メモ

呼び出し制限の名前 :メソッド名 のようにして、アクセス制御を指定する方法もあります。

以下は「morning」と「evening」メソッドに private を設定する例。

class User
  def hello
    p "こんにちは"
  end

  def morning
    p "おはよう"
  end

  def evening
    p "こんばんは"
  end

  private :morning, :evening
end

 

public の使い方

 

public を設定したメソッドは呼び出しに制限がなく、クラスの外からでも呼び出すことができます。

あらかじめ設定されているデフォルトの呼び出し制限なので、とくに明示的に指定する必要はありません。

 

プログラム例 その1

以下のプログラムでは、何も呼び出し制限の指定がないので「hello」メソッドは public に設定されています。

プログラム
class User
  def hello
    p "こんにちは"
  end
end

user = User.new
user.hello
実行結果
"こんにちは"

public に設定されているメソッドはクラスの外からでも呼び出せるので、user.hello で「hello」メソッドが呼び出せることが確認できます。

 

プログラム例 その2

以下の例では private の記述以下にある「morning」と「evening」メソッドは private が設定されていますが、さらにその下の「night」メソッドは public にしたいので、明示的に public を指定しています。

プログラム
class User
  def hello
    p "こんにちは"
  end

  private

  def morning
    p "おはよう"
  end

  def evening
    p "こんばんは"
  end

  public

  def night
    p "おやすみ"
  end
end

user = User.new
user.night
実行結果
"おやすみ"

「night」メソッドは public に設定してあるので、user.night でクラスの外から「night」メソッドが呼び出せることが確認できます。

 

private の使い方

 

private を設定したメソッドはクラスの外からは呼び出せません。同じインスタンス内でのみ、関数形式で呼び出すことができます。

 

プログラム例 その1

以下の例では、private に設定した「morning」メソッドをクラスの外から呼び出そうとしているため、エラーとなります。

プログラム
class User
  private

  def morning
    p "おはよう"
  end
end

user = User.new
user.morning

クラスの外から user.morning で「morning」メソッドを呼び出そうとして、エラーとなります。

 

プログラム例 その2

今度はクラス内で「morning」メソッドを呼び出してみます。こちらはエラーになりません。

プログラム
class User
  def greeting
    morning
  end

  private

  def morning
    p "おはよう"
  end
end

user = User.new
user.greeting
実行結果
"おはよう"

user.greeting で「greeting」メソッドを呼び出し、その中で「morning」メソッドを呼び出しています。private に設定しているメソッドは同じインスタンス内で呼び出せるので、「morning」が呼び出されて「おはよう」が表示されることが確認できます。

 

protected の使い方

 

protected を設定したメソッドはクラスの外からは呼び出せません。同じインスタンス内で呼び出すことができます。また、他のインスタンスでも同じクラスやサブクラスのメソッドであれば呼び出せます。

メモ

特殊な用途になるので、使用頻度は少ないです。

 

プログラム例 その1

以下の例では、protected に設定した「morning」メソッドをクラスの外から呼び出そうとしているため、エラーとなります。

プログラム
class User
  protected

  def morning
    p "おはよう"
  end
end

user = User.new
user.morning

クラスの外から user.morning で「morning」メソッドを呼び出そうとして、エラーとなります。

 

プログラム例 その2

今度はクラス内で「morning」メソッドを呼び出してみます。こちらはエラーになりません。

プログラム
class User
  def greeting
    morning
  end

  protected

  def morning
    p "おはよう"
  end
end

user = User.new
user.greeting
実行結果
"おはよう"

user.greeting で「greeting」メソッドを呼び出し、その中で「morning」メソッドを呼び出しています。protected に設定しているメソッドは同じインスタンス内で呼び出せるので、「morning」が呼び出されて「おはよう」が表示されることが確認できます。

 

プログラム例 その3

protected を設定したメソッドは、以下のように他のインスタンスであっても同じクラスやサブクラスのメソッドであれば呼び出せます。

プログラム
class User
  def set_name(name)
    @name = name
  end

  def become_friends(user)
    p "#{get_name}さんと#{user.get_name}さんが友達になりました"
  end

  protected

  def get_name
    @name
  end
end

user1 = User.new
user1.set_name("佐藤")

user2 = User.new
user2.set_name("鈴木")

user1.become_friends(user2)
実行結果
"佐藤さんと鈴木さんが友達になりました"

user1.become_friends(user2) で「become_friends」メソッドを呼び出し、その中の p "#{get_name}さんと#{user.get_name}さんが友達になりました" のコードで「get_name」メソッドを呼び出しています。1つ目の get_name では自身のインスタンスのメソッドを呼び出しています。2つ目の user.get_name では引数で渡した「user2」インスタンスのメソッドを呼び出しています。

2つ目の user.get_name では、もし「get_name」メソッドが private に設定されていた場合は、外部のメソッドのため直接呼び出すことはできませんが、今回のように protected に設定されていた場合、 「user2」インスタンスは呼び出し元と同じ「User」クラスから生成されているため、直接 呼び出すことができます。

 

まとめ

以上、「private」や「protected」の使い方でした!

 

ここまでの内容をまとめておきます。

  • クラスの中で定義できるメソッドは、外から直接 呼び出せないようにアクセス制御を設定することができる。
  • publicprivateprotected をクラス内で書くと、それ以降のメソッドはすべて指定した呼び出し制限が設定される。
  • public を設定したメソッドは呼び出しに制限がなく、どこからでも呼び出すことができる。デフォルトではこの設定になっている。
  • private を設定したメソッドはクラスの外からは呼び出せない。同じインスタンス内でのみ、関数形式で呼び出すことができる。
  • protected を設定したメソッドはクラスの外からは呼び出せない。同じインスタンス内で呼び出すことができる。また、他のインスタンスでも同じクラスやサブクラスのメソッドであれば呼び出せる。