【実用性皆無】 Rubyでクラスを動的に生成する(継承もできるよ!)
クラスを動的に定義したいな〜って時ありませんか?
例えば、Ramen
というクラスを動的に定義するには以下のようにします。
Object.const_set("Ramen", Class.new)
こうすると、Ramen
クラスを使えるようになります。
Object.const_set("Ramen", Class.new)
ramen = Ramen.new
でも、あまりこういう使い方は必要ないかもですね🤔
クラスを動的に定義するときに、継承したいな〜って時ありませんか?
例えば、以下のような Ramen
クラスがあったとします。
class Ramen
end
これを継承した、MisoRamen
を作る場合はこうです。
class Ramen
end
Object.const_set("MisoRamen", Class.new(Ramen))
こうすると、MisoRamen
クラスを使えるようになります。
class Ramen
end
Object.const_set("MisoRamen", Class.new(Ramen))
miso_ramen = MisoRamen.new
でも、こういう使い方もあまり必要ないかもですね🤔
moduleをネストして、クラスを動的に定義したいな〜って時ありませんか?
例えば、Miso
モジュールをネストして Miso::Ramen
というクラスを動的に定義するには以下のようにします。
module Miso
end
Miso.const_set("Ramen", Class.new)
こうすると、Miso::Ramen
クラスを使えるようになります。
module Miso
end
Miso.const_set("Ramen", Class.new)
miso_ramen = Miso::Ramen.new
これもどこで使うんでしょう🤔
動的に定義したmoduleをネストして、動的にクラスを定義したいな〜って時ありませんか?
例えば、Miso
モジュールを動的に定義し、Miso
モジュールをネストして Miso::Ramen
というクラスを動的に定義するには以下のようにします。
Object.const_set("Miso", Module.new)
Miso.const_set("Ramen", Class.new)
こうすると、Miso::Ramen
クラスを使えるようになります。
Object.const_set("Miso", Module.new)
Miso.const_set("Ramen", Class.new)
miso_ramen = Miso::Ramen.new
ほんとにこれはどこで使うんでしょう🤔
動的に定義したmoduleをネストして、動的にクラスを定義するときに、継承したいな〜って時ありませんか?
例えば、以下のような Ramen
クラスがあったとします。
class Ramen
end
例えば、Miso
モジュールを動的に定義し、Miso
モジュールをネストして Miso::Ramen
というクラスを動的に定義して、Ramen
クラスを継承するには以下のようにします。
class Ramen
end
Object.const_set("Miso", Module.new)
Miso.const_set("Ramen", Class.new(Ramen))
こうすると、Miso::Ramen
クラスを使えるようになります。
class Ramen
end
Object.const_set("Miso", Module.new)
Miso.const_set("Ramen", Class.new(Ramen))
miso_ramen = Miso::Ramen.new
普段使う場所あるんでしょうか🤔
どこで使うねーん!
どこで使いましょうね、無理矢理考えてみましょう・・・
あっ!!
これらの技術を使えば、プロジェクトに定義されていないはずの
「ぼくのかんがえたさいきょうのラーメン」 クラスを作れますね!!
class Ramen
end
ideas = %w(Boku No Kangaeta Saikyo No)
ideas.size.times do |i|
parent = i.zero? ? Object : Object.const_get(ideas[0...i].join("::"))
parent.const_set(ideas[i], Module.new)
end
Object.const_get(ideas.join("::")).const_set("Ramen", Class.new(Ramen))
idea_ramen = Object.const_get(ideas.join("::"))::Ramen.new
puts idea_ramen.class
#=> Boku::No::Kangaeta::Saikyo::No::Ramen
いや使わないからーーーー!!!!!!
最後に
「なんでこんなことをしようとしたか想像つかない」って?自分もそう思います。
株式会社mofmofの「水曜日の個人開発」という取り組みの中でアプリを作っている時に、特定のモデルを継承したモデルを何個も定義するの面倒だな・・・って思ったんです。
それで調べていたら、「できるやーん!」ってなって実装してたんですけど、
結局使うのはやめました。
(やめたんかーーーい!!!)
面倒だけど、ちゃんと定義した方が将来の自分のためになると思いました。
(保守性の観点とかね!)
(忘れっぽいから「これなんだっけ?」ってなっちゃうからね!)
(メタプロしたかっただけなんじゃないの??)
(そう思う!!)
(でも、楽しかったから記事にしちゃった!!)
Discussion