instance_evalとは
instance_evalは、任意のオブジェクトの特異メソッドを定義したり、そのオブジェクト自身が参照できるインスタンス変数を定義、更新をすることができる。
使用例
# Fooクラスの定義
class Foo
def initialize
@foo = 'foo'
end
end
# Fooクラスのインスタンスを作成
foo = Foo.new
foo.instance_eval do
# fooにインスタンス変数を定義
@bar = 'bar'
# fooの特異メソッドを定義
def baz
puts 'baz'
end
end
puts foo.baz #=> 'baz'
instance_execとは
これもinstance_evalメソッドと似ていて、レシーバのインスタンス元でブロックを実行します。
引数を渡すと、それがブロックの引数として渡されます。
# Fooクラスの定義
class Foo
def initialize
@foo = 'foo'
end
end
# Fooクラスのインスタンスを作成
foo = Foo.new
puts foo.instance_exec(5) {|x| @foo * x } #=> => "foofoofoofoofoo"
hello = proc {
"Hello! #{@name}"
}
puts x.instance_exec(&hello) #=> "Hello! foo"
instance_evalとinstance_execの違い
instance_evalだと、インスタンス変数にしかアクセス出来ないが、
instance_exec を使えばブロックに引数を渡せます。
class_evalとは
class_evalは、クラスに特異メソッドを追加したり、そのクラス自身のインスタンス変数(orクラスインスタンス変数)やクラス変数を定義、更新することが出来る。
このように、class_evalの中で、インスタンス変数を定義しようとすると、それはクラスのクラスインスタンス変数になる。
使用例
# Fooクラスの定義
class Foo
def initialize
@foo = 'foo'
end
end
Foo.class_eval do
# クラスインスタンス変数の定義
@bar = 'bar'
# クラス変数の定義
@@baz = 'baz'
# 特異メソッドの定義
def hello
puts 'Hello!'
end
end
# Fooクラスのインスタンスを作成
foo = Foo.new
# fooオブジェクトが持っているインスタンス変数を参照
puts foo.instance_variables #=> @foo
# Fooクラスが持っているインスタンス変数を参照
puts Foo.instance_variables #=> @bar
# Fooクラスが持っているクラス変数を参照
puts Sample.class_variables #=> @@baz
# fooオブジェクトの特異メソッドhelloを実行
puts foo.hello #=> "Hello!"
まとめ
下記のポイントを押さえておけば間違い無いです!
instance_eval
- レシーバーであるインスタンスのインスタンス変数を定義、更新することが出来る。
- 任意のオブジェクトの特異メソッドを定義、更新することが出来る。
instance_eval
- instance_evalメソッドと大まかな動作は変わらないが、引数を渡すと、それがブロックの引数として渡されます。
class_eval
- クラスに特異メソッドを追加したり、そのクラス自身のインスタンス変数(orクラスインスタンス変数)やクラス変数を定義、更新することが出来る。
- class_eval内でのインスタンス変数定義は、そのクラスのクラスインスタンス変数となる。