難しいが強力! Rubyのメタプログラミング、self、特異クラス/メソッド、オープンクラスとモンキーパッチ若手エンジニア/初心者のためのRuby 2.1入門(12)(2/4 ページ)

» 2015年01月06日 20時15分 公開
[著:麻田優真、監修:山根剛司,株式会社アジャイルウェア]

クラス自体にメソッドを定義する「self」「特異メソッド」「特異クラス」

 多くのオブジェクト指向プログラミング言語では、「Klass」クラスに対して、「Klass.hoge」という形でメソッドを呼び出せるような仕組みが備わっています。言語により名前は違いますが、一般的に「クラスメソッド」と言う場合が多いようです。

 もちろん、Rubyでも同様のことができます。基本的な機能のように思えますが、実のところ、Rubyのメタプログラミングを理解する上で大切な、「self」「特異メソッド」「特異クラス」といった概念が登場する、奥の深い世界なのです。ここでは、それらの概念について説明します。

「現在のオブジェクト」を表すself

  • pryでselfを感じよう

 Rubyでコードを書いていると、そこにはいつも「self」が存在します。とはいえ、普段それを意識することはあまりないでしょう。「self」はRubyに組み込まれている読み取り専用の変数です。インスタンス変数にアクセスする場合や、メソッドを呼び出す場合にはこの「self」が重要な鍵となります。

 では、pryを使って、身近に存在する「self」を感じてみましょう。

[1] pry(main)> self
=> main
[2] pry(main)> self.class
=> Object

 Rubyのインタプリターを開いた状態を「トップレベル」と呼び、トップレベルでの「self」、すなわち現在のオブジェクトは「main」であることが[1]から分かります。[2]では、その「main」のクラスを「class」メソッドを使って調べており、「Object」クラスであることが分かります。つまり、トップレベルでは、「self」は「Object」クラスのオブジェクトである、ということです。

  • selfを観察する

 では、簡単なクラスの例を使って、「self」に何が入っているのかを観察しましょう。meta_programming_02.rbにコードを示します。

  1. puts "====================="
  2. p self
  3. p self.class
  4. puts "====================="
  5. class Rabbit
  6. puts "====================="
  7. p self
  8. p self.class
  9. puts "====================="
  10. def jump
  11. puts "====================="
  12. p self
  13. p self.class
  14. puts "pyon pyon"
  15. puts "====================="
  16. end
  17. end
  18. Rabbit.new.jump
meta_programming_02.rb

$ ruby meta_programming_02.rb 
=====================
main
Object
=====================
=====================
Rabbit
Class
=====================
=====================
#<Rabbit:0x007fc43b0daf78>
Rabbit
pyon pyon
=====================

 コードの1~4行目は、トップレベルでの「self」が何であるかを示しています。出力は実行例の2~5行目が対応しています。pryで確かめた時と同様に、トップレベルでの「self」は「main」という名前のオブジェクトを返し、そのクラスは「Object」です。

 コードの7~10行目は、クラスの定義の中での「self」が何であるかを示しています。出力は実行例の6~9行目が対応しています。クラス定義の中では、「self」はRabbitクラスそのもの(Rubyではクラスそのものも、「Class」クラスのオブジェクトであることを思い出してください!)です。

 コードの13~17行目は、メソッドの定義の中での「self」が何であるかを示しています。出力は実行例の10~14行目が対応しています。メソッド定義の中では、「self」はRabbitクラスのオブジェクトであることが分かります。

 このように、「self」の中身は、コードの場所によって変わることが分かります。

  • 暗黙的なself

 ここまでの例で、「self」は確かにそこにあって、コードの場所によって変わることを確認しました。では、「self」はどこで役に立つのでしょうか? 答えは、メソッドやインスタンス変数へアクセスのときに役立ちます。その例をmeta_programming_03.rbとmeta_programming_04.rbに示しましょう。

  1. class Rabbit
  2. def initialize
  3. @roar = "boo"
  4. end
  5. def _speak
  6. puts @roar
  7. end
  8. def speak
  9. _speak
  10. end
  11. end
  12. Rabbit.new.speak
meta_programming_03.rb
  1. class Rabbit
  2. def initialize
  3. @roar = "boo"
  4. end
  5. def _speak
  6. puts @roar
  7. end
  8. def speak
  9. self._speak
  10. end
  11. end
  12. Rabbit.new.speak
meta_programming_04.rb
$ ruby meta_programming_03.rb 
boo
meta_programming_03(04).rbの実行例

 これらのコードでは、「Rabbit」クラスを定義して、コンストラクターでインスタンス変数「@roar」に、文字列booを設定しています。また、「_speak」および「speak」メソッドを定義しており、「speak」は「_speak」を呼び出すことによって、インスタンス変数「@roar」の内容を出力しています。

 meta_programming_03.rbとmeta_programming_04.rbの違いは、11行目の「_speak」の呼び出し部分です。これまで、meta_programming_03.rbのような記法を利用していましたが、これはmeta_programming_04.rbのように、明示的に「self」を指定することで呼び出すこともできます。

 Rubyでは、「{レシーバー(メソッドを呼び出す対象のオブジェクト)}.{メソッド}」という形でメソッドを呼び出すことが基本です。あるオブジェクト「obj」のメソッド「hoge」を呼び出す場合は、「obj.hoge」となります。

 レシーバーを省略した場合(meta_programming_03.rbの11行目)は、レシーバーとして暗黙的に「self」が使われるため、無事に「Rabbit」クラスの「_speak」メソッドが呼び出されています。また、7行目のようにインスタンス変数にアクセスする場合は、「self」のインスタンス変数が探索されて返されます。

Copyright © ITmedia, Inc. All Rights Reserved.

スポンサーからのお知らせPR

Coding Edge 記事ランキング

本日月間

注目のテーマ

4AI by @IT - AIを作り、動かし、守り、生かす
Microsoft & Windows最前線2025
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。