【Ruby】define_methodについて調べました
はじめに
せっかく調べたのに忘れてしまうため、メモを残しておく。
今回は、ライブラリの挙動を確認していたところ
define_method
が書かれており、復習も兼ねて調べました。
環境
前提条件
- irbかPryが動作すること
やり方
実行
[1] pry(main)> class Animal [1] pry(main)* { cat: 'にゃー', dog: 'わん' }.each do |name, message| [1] pry(main)* # 動的にクラスやモジュールを定義でき、defによるメソッド定義をしなくてもよい [1] pry(main)* # メソッド本体はブロックで記述する [1] pry(main)* define_method(name) do [1] pry(main)* message [1] pry(main)* end [1] pry(main)* end [1] pry(main)* end => {:cat=>"にゃー", :dog=>"わん"} [2] pry(main)> [3] pry(main)> puts Animal.new.cat にゃー => nil [4] pry(main)> [5] pry(main)> class Animal2 [5] pry(main)* { cat: 'にゃー', dog: 'わん' }.each do |name, message| [5] pry(main)* # ブロックにブロック引数を加えるとブロック引数がメソッドの引数になる [5] pry(main)* # ブロック引数:name [5] pry(main)* define_method(name) do |num| [5] pry(main)* message * num [5] pry(main)* end [5] pry(main)* end [5] pry(main)* end => {:cat=>"にゃー", :dog=>"わん"} [6] pry(main)> [7] pry(main)> # メソッドの引数:2 [8] pry(main)> puts Animal2.new.dog(2) わんわん => nil [9] pry(main)> class Animal3 [9] pry(main)* end => nil [10] pry(main)> [11] pry(main)> { cat: 'にゃー', dog: 'わん' }.each do |name, message| [11] pry(main)* # ブロックをオブジェクトとして定義する [11] pry(main)* proc = Proc.new { |num| message * num } [11] pry(main)* # class_evalは、ブロックをクラス定義やモジュール定義の中のコードであるように実行する [11] pry(main)* # ブロックの戻り値がメソッドの戻り値になる [11] pry(main)* Animal3.class_eval { define_method(name, proc) } [11] pry(main)* end => {:cat=>"にゃー", :dog=>"わん"} [12] pry(main)> [13] pry(main)> puts Animal3.new.cat(3) にゃーにゃーにゃー => nil
まとめ
defでメソッド定義しなくてもメソッドを定義するという
初見殺しな面もありますが、メタプログラミングをする上で
扱うものの1つだと思うのでしっかり覚えておきます。