⚙️
instance_evalでインスタンスに機能を追加する
概要
Rubyの「instance_eval」を使って、
インスタンスに対して動的に機能を付与してみる。
環境
- macOS Catarina
- ruby 3.0.0
instance_evalとは
引数で与えた文字列をRubyプログラムとして評価し、
その呼び出し元のインスタンスに評価した処理を実行できるメソッドである。
具体例として、以下のようになる。
class Sample
def initialize
@x = 10
end
end
sample = Sample.new
p sample #<Sample:0x00007fe6ed9e6868 @x=10>
sample.instance_eval "@y = 20"
p sample #<Sample:0x00007fe6ed9e6868 @x=10, @y=20>
この具体例のように、1回目のsample
(Sampleクラスのインスタンス)の出力では、
@x
のみ保持しているが、そのあとにinstance_evalで@y
を格納しており、
2回目のsample
の出力では、@y
もインスタンス変数として保持できている。
instance_eval
は、そのレシーバとなったインスタンスに対してのみ、
評価したプログラムを適用する。
そのため、インスタンスごとに固有の処理を追加できるイメージである。
利用例
例えば、ゲームなどでキャラクター固有の処理を動的に読み込ませて処理できるようにする、
というようなことができるのではと思う。
ゲームの各キャラクターの固有処理は、それぞれファイルに記述しておき、
ゲームの進行中にそのファイルを読み込みinstance_evalで評価&インスタンスに付与、
といったイメージである。
具体例として、以下のようになる。
character.rb
class Character
def initialize
...
end
# ここに共通処理を実装するのもいい.
...
end
c1 = Character.new
c1.instance_eval File.read './characters/chara_1.rb'
p c1
c1.ability
c2 = Character.new
c2.instance_eval File.read './characters/chara_2.rb'
p c2
c2.ability
./characters/chara_1.rb
@name = "ブレイブリーファルコン"
@power = 5
@health = 6
def ability
p "#{@name} executes own ability."
p "ブレイブショット"
end
./characters/chara_2.rb
@name = "見習い剣士"
@power = 2
@health = 3
def ability
p "#{@name} executes own ability."
p "クリティカルバスター"
end
実行結果
❯❯❯ ruby character.rb
#<Character:0x00007fe02b905cc8 @name="ブレイブリーファルコン", @power=5, @health=6>
"ブレイブリーファルコン executes own ability."
"ブレイブショット"
#<Character:0x00007fe02b904288 @name="見習い剣士", @power=2, @health=3>
"見習い剣士 executes own ability."
"クリティカルバスター"
このように、それぞれのキャラクターの設定ファイル(ステータスやアビリティ内容)を読み込み、それぞれのインスタンスで固有の処理が実行できている。
Discussion