Different point between
class_eval
andinstance_eval
class Person
end
Person.class_eval do
def say_hello
"Hello!"
end
end
jimmy = Person.new
jimmy.say_hello # "Hello!"
Trong ví dụ ở trên thì, class_eval
cho phép ta định nghĩa method bên ngoài class Person, tất nhiên chúng ta không mở lại class Person.
Class Person không biết method say_hello cho tới khi nó runtime. -> metaprogramming
code sinh ra code là đây
Trường hợp khác, ta có ví dụ sau:
class Person
end
Person.instance_eval do
def human?
true
end
end
Person.human? # true
Trong ví dụ trên thì instance_eval
cũng hoạt động giống class_eval
nhưng khác biệt ở chỗ là môi trường của biến instance đang đứng (context).
Nó gây ra sự bối rối nhất định.
Ví dụ 1, class_eval
tạo ra instance_methods còn ví dụ 2 instance_eval
tạo ra class_methods.
Bởi vì, class_eval
là 1 method của class Module
, nghĩa là receiver sẽ là 1 module hoặc là 1 class. Block mà ta pass phía sau class_eval
sẽ được thực thi trong context của class đó. Cho nên khi ta định nghĩa method với def
trong block này nghĩa là định nghĩa method inside class nên nó trở thành instance_methods trong class này.
Mặt khác, instance_eval
là 1 method của class Object
, nghĩa là recevier là 1 object. Block mà ta pass sau instance_eval
sẽ được thực thi trong context của object đó. ví dụ là Person.instance_eval
được thực thi trong ngữ cảnh của Person
object. Và nên nhớ rằng tên của class là 1 class object và define method trong context Class sẽ tạo ra class_methods
.
Tóm lại đơn giản: MyClass.class_eval thì tạo instance_methods còn MyClass.instance_eval thì tạo ra class_methods.
Done!