動的メソッド
メソッドを呼び出す方法
- ドットを使う
- send()を使う
- send()メソッドの第一引数は呼び出すメソッド名 => 文字列またはシンボル
- その他の引数はそのままメソッドに渡される
send()を使えばコードの実行時に呼び出すメソッドを直前に決められる。なので動的な処理が可能になる。これを動的ディスバッチ
と呼ぶ。
プライバシー問題
send()メソッドの問題はprivate
メソッドも呼ばれるということだ。
- 例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
プライバシーの尊重のため、public_send()
を使う方法もある。
- 例2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
メソッドを動的に定義
- define_method()
Module#define_method()を使えば、メソッドをその場で定義できる。
1 2 3 4 5 6 7 8 9 |
|
define_method
はClassの中で実行され、my_method()
がC
クラスのインスタンスメソッドとして定義される。実行時にメソッドを定義するこの技術を動的メソッド
と呼ぶ。
method_missing()
method_missing()のオーバーライド
method_missing()
メソッドはBasicObject
のインスタンスメソッドだ。つまり、BasicObject
を継承しているObject
を継承するオブジェクトはmethod_missing()
を持っているということになり、もちろんオーバーライドもでき、存在しないメソッドに対するハンドリングもできるということだ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
ゴーストメソッド
同じようなメソッドをたくさん定義しなければならないとき、いちいち定義するより、method_missing()を呼び出す方がもっと楽かもしれない。method_missing()での処理は呼び出し側からは通常の呼び出しのように見える。しかし、レシーバに対応するメソッドは見当たらない。これはゴーストメソッド
と呼ぶ。上記の例ではhello()
がゴーストメソッドなるのだ。
もっとmethod_missing()
メソッド名が衝突したら
- 例
1 2 3 4 5 6 7 8 9 10 11 |
|
上記のコードでは
1 2 |
|
とプリントされると予想したけど、プリントされずArgumentError
になってしまった。
これの問題はObject
から継承されたメソッドの中でdisplay
というメソッドがあり、method_missing()
が呼ばれなかったからだ。
これはは必要ないメソッドを全部削除することで対応できる。メソッドをすべて削除することをブランクスレート
と呼ぶ。
- 例2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
このコードは予想通りmethod_missing()
を呼び出すことができる。
まとめ
- メソッドは
send()
でも呼び出せる send()
はprivate
メソッドも呼び出せるため、public_send()
を使うこともできるdefine_method()
でメソッドを動的に定義できるmethod_missing()
を利用すると存在しないメソッド、ゴーストメソッドに対するハンドリングや処理ができる