メタプログラミングRubyを読んでいます。完全自分用のメモ記事です。
第2章で特に参考になった部分を中心に書いています。
メタプログラミングとは
コードを記述するためのコードを書くことである
2章
オープンクラス
1 2 3 4 | |
とある場合、 to_money は以下のように Numeric クラスを拡張して実装されている。
1 2 3 4 5 | |
Rubyは標準クラスでも気軽に拡張できる。これをモンキーパッチと呼ぶ。
しかし例えば拡張したメソッドが標準クラスのメソッドだった場合、その影響範囲が大きくなってしまう。
モンキーパッチの代替案としては、Refinements などを使うことである。
Classの親クラスは Module
1
| |
Class はオブジェクトの生成やクラスを継承するためのインスタンスメソッド new, allocate superclass を追加したモジュールである。
load と require の違い
- load => loadはコードを実行するために使う。呼び出す度にファイルを実行する - require => requireはライブラリをインポートするために使う。ファイルは一度しか読み込まない。
モジュールの継承関係
継承チェーンはクラスからスーパークラスに向かって進む。 それだけではなく、継承チェーンにはモジュールも含まれる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
このようにM1やKernelなどのModuleも継承関係に含まれている事がわかる。
ちなみに、モジュールがすでにチェーンに存在していた場合は、2回目の挿入を無視する。 (何度も継承チェーンに同じオブジェクトが含まれることはない)
Rubyにおける private について
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
Refinementsについて
module で限定されたスコープの中でのみ、Stringを限定して拡張できる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
これにより、モンキーパッチで発生するようなグローバルな変更を避けることができる。
ただし、Refinementsは新しい機能で、将来挙動が変わる可能性がある。
そのことを理解したうえで、プログラムを書くべきである。
まとめ
- オブジェクトは複数のインスタンス変数とクラスへのリンクで構成
- インスタンス目ドッドはオブジェクトの Class に住んでいる
- クラスは Class クラスのオブジェクトである。クラスは単なる定数である
- Class は Module のサブクラスである
- Module は基本的にはメソッドをまとめたものである
- クラスは new でインスタンス化したり、 superclass で階層構造を作ったりできる
- クラスはそれぞれ、BasicObject まで続く継承チェーンを持っている
- クラスにモジュールをinclude(prepend)すると、そのクラスの継承チェーンの真上(下)にモジュールが挿入される
- メソッドを呼び出すときには、レシーバがselfになる
- モジュール(あるいはクラス)を定義するときには、そのモジュールがselfになる
- インスタンス変数は常にselfのインスタンス変数とみなされる