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’)
- ホワイトペーパー
- 企画特集
- 話題のタグ
SQLite対応アプリのデータベースファイルを閲覧する
グーグル、「Google Buzz」を発表--Gmailのソーシャル機能を強化
「H.264」ストリーミングのロイヤリティ無料期間が延長
マイクロソフト、「Office 2010」のRC版をリリース
DBのパフォーマンスに困ってませんか?
通販サイトのアクセス集中からの危機を救う
アンケートから見るセキュリティ対策の実態
仮想環境のバックアップは難しいのか
Xbox Live インディーズゲーム開発の軌跡
事例 VMwareでデータセンターをクラウド化
利用者の理想を追求した最新レンタルサーバ
身近な業務をCRMが変革!
新しい視点のレンタルサーバが誕生!
経営統合後の事業損益構造の見える化を実現
アプリケーション仮想化 3つの課題
御社はまだフリーの転送サービスですか?
仮想化をダメにするストレージの実態
レガシーアプリケーションの稼働どうしてる?