0
0

メソッドの公開レベル

Posted at

Rubyにおけるメソッドの公開レベルには、public、protected、privateの3種類があります。それぞれメソッドへのアクセスを制御するために使いますが、特にprivateメソッドを指定する際にはいくつかの注意点があります。

  1. 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のように外部から直接呼び出すことはできません。

  1. レシーバを明示できない(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と直接呼び出す必要があります。

  1. サブクラスでも呼び出せない
    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
  1. privateメソッドのユースケース
    privateメソッドは、クラス内部での実装の詳細を隠蔽するために使います。外部に公開する必要のないメソッドや、クラスの内部処理をまとめるための補助的なメソッドをprivateにすることが一般的です。

  2. 例外:クラスメソッドの場合
    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になるように設計しましょう。
これらを理解して正しく使うことで、クラスの設計がより堅牢になります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0