こんにちは。ゆうすけです。
業務で僕がハマったRubyのメソッドの呼び出しエラーについて丁寧に解説していきます。
この記事を読めばRubyのクラスメソッド・インスタンスメソッドについてざっくり理解できるようになると思います。
↓の例題をご覧になって、答えと理由を即答できなかった方は是非読んでみてください!
1. 例題
こちらのコードの出力はどうなるでしょうか?
class A def self.b c end private def c p 'Yeah!' end end A.b
① Yeah!
② エラーとなる
Twitterでアンケートをとってみた結果がコチラです。
```ruby
— ゆうすけ@Railsエンジニア (@ysk_pro) 2018年10月24日
class A
def self.b
c
end
private
def c
p 'Yeah!'
end
end
A.b
```
3. 解説
この問題を理解するために、順を追って解説していきます。
3-1. メソッドのレシーバとは?
通常、メソッドは以下のように呼び出すと思います。
オブジェクト.メソッド名(引数1, ・・・)
このときの、オブジェクトをレシーバと呼びます。
メソッドを実行することをオブジェクトにメッセージを送る、という考え方をするので、メッセージを受け取るという意味からレシーバと呼ばれています。
3-2. インスタンスメソッド・クラスメソッドとは?
インスタンスをレシーバとするメソッドをインスタンスメソッドと呼びます。そのままですね。
同様に、クラスをレシーバとするメソッドをクラスメソッドと呼びます。
例えば、インスタンスを作るときによく使う
User.new
の .new はクラス(User)をレシーバとしているのでクラスメソッドです。
直接インスタンスを操作するわけではないけれども、そのクラスに関連する操作を行いたい場合に、よくクラスメソッドが用いられます。
3-3. インスタンスメソッド・クラスメソッドの定義の仕方
こちら↓のx がインスタンスメソッドです。よく見る形ですね。
class A def x c end end
そしてこちら↓の y がインスタンスメソッドです。self. をつけるとクラスメソッドになります。
class A def self.y c end end
クラスメソッドは↓の z のように定義することもでき、以下のように定義したメソッドは特異メソッドと呼ばれます。
class A class << self def z c end end end
3-4. メソッド内で別のメソッドの呼び出す方法
メソッドの中では、そのメソッドのレシーバ自身を参照するのに self を用います。
さらに、メソッドの中ではレシーバを省略してメソッドを呼び出す出すことができます。
レシーバを省略してメソッドを呼び出すと、暗黙的に self がレシーバとなります。
すなわち、インスタンスメソッドの中でレシーバを省略してメソッドを呼び出すと、呼び出されるのはインスタンスメソッドとなり、クラスメソッドの中でレシーバを省略してメソッドを呼び出すと、呼び出されるのはクラスメソッドとなります。
<プラス知識>
private というのは、メソッドをレシーバを指定して呼び出せないようにしています。
つまり、レシーバを省略した形式でしか呼び出せないために、インスタンスの外側から利用できなくなっているのです。
3-5. ここで問題を再度見てみると...
class A def self.b c end private def c p 'Yeah!' end end A.b
① Yeah!
② エラーとなる
b メソッドはクラスメソッドだということがまず分かります。
よって、その b メソッドの中で呼び出している c メソッドのレシーバはAクラスとなるため、c という名前のクラスメソッドを探しにいきます。
しかし、c という名前のクラスメソッドは存在しないため(存在するのはc という名前のインスタンスメソッドのみ)エラーとなるのです。
cメソッドをクラスメソッドにした、↓のコードであれば、出力は Yeah! となります。
class A def self.b c end def self.c p 'Yeah!' end private_class_method :c end
クラスメソッドをprivateにする方法は↑のコードの通りです。
4. おわりに
いかがでしたでしょうか。
僕は業務でクラスメソッドからインスタンスメソッドが呼べずに1時間程ハマるまで、クラスメソッドとインスタンスメソッドの区分が曖昧になっていました。
この記事で皆さまの理解が少しでも深まると嬉しいです。
ちなみに、僕がこの件でハマった際は、↓の本の解説で解決することができました。
解説がとても丁寧で分かりやすいので、Rubyについて深く知りたい方にオススメです!
- 作者: 高橋征義,後藤裕蔵
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2016/02/26
- メディア: Kindle版
- この商品を含むブログを見る
改めて読んで見ても、「ああ、そういうことだったのか」という気づきが多くて面白いですよー!
Enjoy Ruby!