Rubyによるメタプログラミング
翻訳校正:石橋啓一郎
連載2回目の本記事では、Rubyのメソッドの定義方法と呼び出し方法について詳しく述べる。
最初のコラムでは、Rubyの構文は柔軟であり、ドメイン固有言語(DSL)を作るのに非常に適していると述べた。
さて、これからはRubyのメソッドの定義方法と呼び出し方法について詳しく述べる。さらに、Rubyのメタプログラミングによって、DSLにコードの実行中に新しいクラスを作成させる方法について説明する。これを読めば、DSLの作成に必要なツールの大半を知ることができる。
われわれは既に、Rubyではあるクラスにnewメソッドを送ることでオブジェクトが生成されることを学んでいる。
book = Book.new
クラスがnewメソッドを受け取ると、新しいオブジェクトのスペースに割り当て、もしinitializeインスタンスメソッドが存在すればそれを呼び出し、新しいオブジェクトを有効な状態にする。newメソッドに渡される引数は、自動的にinitializeに渡される。例えば次のようになる。
class Book def initialize(title, author, isbn) @title = title @author = author @isbn = isbn end end book = Book.new(‘War and Peace’, ‘Tolstoy’, ‘0375760644’)
この実装では、本に関するオブジェクトを生成する際には、必ず毎回本のタイトルと著者とISBNを入力しなければならず、詳細を知らない場合でも何らかの値を与えなくてはならない。例えば、私がタイトルだけしか知らない場合、次のような形にしなくてはならない。
book = Book.new(‘To Serve Them All My Days’, ‘Unknown’, ‘’)
これは少し煩わしいし、値が分からない場合にそれをどうコード化するかは、それぞれの開発者の気まぐれに任せてしまうことになる。知らないパラメータについてはデフォルト値が設定されるようになれば便利であり、Rubyにはその方法が用意されている。次のクラス定義の例では、タイトルの値は必ず入力しなくてはならないが、著者とISBNについてはデフォルト値が設定される。
class Book def initialize(title, author=’Unknown’, isbn=nil) @title = title @author = author @isbn = isbn end end
メソッドがパラメタに与えるデフォルト値を持っている場合、それに対応するパラメタは省略することができる。パラメタは位置で指定されることから、もしあるパラメタにデフォルト値を使う場合、それ以降のパラメタはすべてデフォルト値を使わなくてはならない。
book = Book.new(‘War and Peace’, ‘Tolstoy’, ‘0375760644’) #valid book = Book.new(‘War and Peace’, ‘Tolstoy’) #valid book = Book.new(‘War and Peace’) #valid book = Book.new(‘War and Peace’, ‘0375760644’) #valid syntax, but bad semantics
最後の例は構文は合っており実行もできるが、名前が"0375760644"でISBNがnilの本のオブジェクトを生成してしまう。これはおそらく意図していることとは違っているだろう。
では、本のオブジェクトを生成する際に、その本を所有している人のリストも作りたいと思っており、そのリストは任意の長さである場合を考えてみよう。明らかな方法の1つは、所有者を行列として渡すことだ。例えば次のようになる。
class Book def initialize(title, author=’Unknown’, isbn=nil, owners=[]) @title = title @author = author @isbn = isbn @owners = owners end end book = Book.new(‘War and Peace’, ‘Tolstoy’, ‘0375760644’, [‘Steve’, ‘Amanda’, ‘Marty’])
確かにこれでも正しく動くのだが、Rubyではもっと簡単な方法がある。次の例は、前の例と意味的に等価なものだ。
class Book def initialize(title, author=’Unknown’, isbn=nil, *owners) @title = title @author = author @isbn = isbn @owners = owners end end book = Book.new(‘War and Peace’, ‘Tolstoy’, ‘0375760644’, ‘Steve’, ‘Amanda’, ‘Marty’)
- ホワイトペーパー
- 話題のタグ
グーグル、JavaScriptプログラミングツールをリリース
Windowsの歴史 Windows Server 2008編:同じカーネルを持つ「Vista」とは対照的に早くから支持を得たサーバOS
Windowsの歴史 Windows Server 2003 R2編:安定性と先進性の両立目指す「R2」の先駆けとなったOS
モジラ、「Firefox 3.6」の第1ベータ版をリリース
企業ITシステムの企画、構築、運用のイロハ
最大32個のセンサーが電力を徹底管理!
大丈夫?あなたの会社のセキュリティ対策
100万円で実現!中小企業の情報漏えい対策
進むストレージ環境の見直し
―エン・ジャパン厳選求人☆毎週更新―
【最終警告】パンデミック対策特集