[英]Understanding class_eval and instance_eval?
I'm confused as to when I should be using instance_eval
and class eval
.我对何时应该使用
instance_eval
和class eval
感到困惑。
I should or shouldn't use them?我应该还是不应该使用它们?
Answer with simple examples on how to use them.用简单的例子回答如何使用它们。
Thanks a lot.非常感谢。
The class_eval
and instance_eval
are both used to reopen an object and define additional behaviour. class_eval
和instance_eval
都用于重新打开对象并定义其他行为。
They follows the open/closed principle .他们遵循开放/封闭原则。
class_eval
is used to define additional behaviour in the context of a class. class_eval
用于在类的上下文中定义附加行为。
Let's use the following Person
class:让我们使用下面的
Person
类:
class Person
def initialize(name)
@name = name
end
end
Person.class_eval do
def say_hello
puts "Hello! I'm #{@name}"
end
end
j = Person.new "John"
j.say_hello # Hello! I'm John
r = Person.new "Robert"
r.say_hello # Hello! I'm Robert
Both j
and p
can use a new method called say_hello
that wasn't defined in the definition of the class Person
, but on an extension of it. j
和p
都可以使用一个名为say_hello
的新方法,它没有在类Person
的定义中定义,而是在它的扩展中定义。
instance_eval
is used to define additional behavior in the context of a receiving object. instance_eval
用于定义接收对象上下文中的附加行为。
The previous example could be rewritten as:前面的例子可以重写为:
class Person
def initialize(name)
@name = name
end
end
j = Person.new "John"
j.instance_eval do
def say_hello
puts "Hello! I'm #{@name}"
end
end
j.say_hello # Hello! I'm John
Since we used instance_eval
on j
, only the behavior of j
has been redefined, in fact we can't use say_hello
on another instance:因为我们在
j
上使用了instance_eval
,所以只有j
的行为被重新定义了,事实上我们不能在另一个实例上使用say_hello
:
r = Person.new "Robert"
r.say_hello # undefined method `say_hello' for #<Person:0x00007fac43c15b28 @name="Robert"> (NoMethodError)
This is the opposite of class_eval
.这与
class_eval
相反。
class_eval
allows you to open and redefine the behavior of a class in order to extend all instances of the class class_eval
允许您打开并重新定义一个类的行为,以便扩展该类的所有实例instance_eval
allows you to open and redefine the behavior of just an instance of a class instance_eval
允许您打开和重新定义类实例的行为 I'm of the idea that you shouldn't use them, because this can lead to code fragmentation.我认为你不应该使用它们,因为这会导致代码碎片化。
But you have to use them when you want to add behavior on third parties code or when you want to add behavior dynamically.但是当你想在第三方代码上添加行为或者当你想动态添加行为时,你必须使用它们。
Use ClassName.instance_eval to define a class method (one associated with the class object but not visible to instances).使用 ClassName.instance_eval 定义一个类方法(一个与类对象关联但对实例不可见的方法)。 Use ClassName.class_eval to define an instance method (one that applies to all of the instances of ClassName).
使用 ClassName.class_eval 定义实例方法(适用于 ClassName 的所有实例的方法)。
Source: RubyMonk资料来源: RubyMonk
One of the major differences between eval and instance_eval is that with instance_eval you have the choice of explicitly handling the context of self.
eval 和 instance_eval 之间的主要区别之一是使用 instance_eval 您可以选择显式处理 self 的上下文。 As instance_eval is a method on Object it is scoped by the object you specify.
由于 instance_eval 是 Object 上的一种方法,它的范围由您指定的 object 决定。
class_eval is much simpler than instance_eval which works on metaclasses (or the singleton object).
class_eval 比在元类(或 singleton 对象)上工作的 instance_eval 简单得多。 It works on the class as if you were opening it in a text editor and adding new state or behaviour to it.
它在 class 上工作,就像您在文本编辑器中打开它并向其添加新的 state 或行为一样。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.