みずラテ

牛乳と水を2対1で。

【Ruby】メタプログラミングで動的にクラスとメソッドを定義する

やりたいこと

  1. メタプロで、動的にクラスとそのメソッドを定義したい。
  2. Api関係の部分使いたいので、Moduleの配下に定義したい。
  3. 動的に定義したクラスは他のクラスを継承した形にしたい。

方法

  • const_setを使っていく
  • define_methodを使っていく

結果

これでいける!勝つる!

module Hello
  class_list = ['Ohayo','Konnichiwa','Konbanwa']

  #親クラスHelloの動的定義
  const_set(:'Hello', Class.new do
    def hello
      puts 'hello.'
    end
  end)

  #親クラスを継承した子クラスOhayo, Konnichiwa, Konbanwaの動的定義
  #動的にメソッドも定義する
  class_list.each do |v|
    const_set(v.intern, Class.new(Hello) do
      define_method v.downcase do
        puts v + ' desu.'
      end
    end)
  end
end

#実際に使ってみる。

#Ohayoクラスの生成
hello = Hello::Ohayo.new
#親クラスのメソッド呼び出し
hello.hello # -> hello.
#子クラスの動的に定義したメソッドの呼び出し
hello.ohayo # -> Ohayo desu.

ポイント:Classクラスのnewメソッドを理解する

公式リファレンスマニュアルに以下の記載があります。
class Class (Ruby 2.7.0 リファレンスマニュアル)

new(superclass = Object) -> Class
new(superclass = Object) {|klass| ... } -> Class

どういうことか。

1行目については引数に継承したいクラスオブジェクトを入れると、継承してくれる。デフォルトはObjectクラスの子クラスとしてclassが定義される。

2行目についてはブロックを与えるとその中身はclassに紐づく。つまりブロック内にメソッドを直書きすれば良い。

この2点を理解すると、↑のコードは問題なく読めると思います。
あとは適当に外部から取得してきた風に配列の中にクラス名を格納して、順次クラス定義をしているのと、define_methodで動的にメソッド定義してみました。

誰かのお役に立てれば幸い。

今回は以上です。

メタプログラミングRuby 第2版

メタプログラミングRuby 第2版