難しいが強力! Rubyのメタプログラミング、self、特異クラス/メソッド、オープンクラスとモンキーパッチ:若手エンジニア/初心者のためのRuby 2.1入門(12)(2/4 ページ)
オープンソースのオブジェクト指向プログラミング言語「Ruby」の文法を一から学ぶための入門連載。最新版の2.1に対応しています。今回は、Rubyの「黒魔術」といわれるメタプログラミングの概要、self、特異メソッド、特異クラス、オープンクラス、モンキーパッチなどの使い方をコード例を交えて解説します。
クラス自体にメソッドを定義する「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にコードを示します。
puts "=====================" p self p self.class puts "=====================" class Rabbit puts "=====================" p self p self.class puts "=====================" def jump puts "=====================" p self p self.class puts "pyon pyon" puts "=====================" end end Rabbit.new.jump
$ 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に示しましょう。
class Rabbit def initialize @roar = "boo" end def _speak puts @roar end def speak _speak end end Rabbit.new.speak
class Rabbit def initialize @roar = "boo" end def _speak puts @roar end def speak self._speak end end Rabbit.new.speak
$ ruby meta_programming_03.rb boo
これらのコードでは、「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.
関連記事
- 数々の“スペル”で高度なプログラミング:Rubyの魔術
- 公用語に英語、「再起動」したRubyKaigi 2013が東京で開催
いったん終了していたRubyコミュニティ主催の年次イベントが再開。技術色、国際色を強め、盛況のうちに幕を閉じた - Web業界、今から行くならRubyエンジニアが狙い目?
不況で冷え込んでいたIT業界の転職市場に、回復の兆しが見え始めている。だが、業種や職種によって採用数や条件に大きな差異が生まれている。転職市場の動向を追い、自身のキャリア戦略立案に生かしてほしい。 - Ruby 2.0.0がリリース、大規模化対応の機能などを搭載
生誕20年となる節目を迎えて、プログラミング言語「Ruby」の最新版がリリースされた - 新バージョンで何が変わるのか、Rubyはどこへ向かうのか:まつもと×笹田、Ruby 1.9を語る
- いよいよ始まるRuby 1.9への移行:開発コアメンバが語るRubyの今とこれから(前編)
- Rubyの今後の進化の方向性とは?:開発コアメンバが語るRubyの今とこれから(後編)
- 互換性や脆弱性の問題にどう対応していくのか:Rubyが抱える課題、NaClの前田氏が講演
- Rails Hub情報局:「なんでRubyなんか作った!? 迷惑だ!」に対するMatzの答え
- Rails Hub情報局:Rubyはイノベーション言語として選ばれている
- Rails Hub情報局:Rubyのまつもと氏は、一発屋で終わるのか?
- Rails Hub情報局:Rubyに魔法は要らない
- 数々の“スペル”で高度なプログラミング:Rubyの魔術
- 晴読雨読@エンジニアライフ:『たのしい開発 スタートアップRuby』――なぜRubyistたちはあれほど楽しそうなのか
- 「JRuby 1.7.0」登場、1年半ぶりのメジャーアップデート
JavaVM上のRuby実装「JRuby」の最新版となる「JRuby 1.7.0」が、10月22日にリリースされた。