[英]Understanding class_eval and instance_eval?
我对何时应该使用instance_eval
和class eval
感到困惑。
我应该还是不应该使用它们?
用简单的例子回答如何使用它们。
非常感谢。
class_eval
和instance_eval
都用于重新打开对象并定义其他行为。
他们遵循开放/封闭原则。
class_eval
用于在类的上下文中定义附加行为。
让我们使用下面的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
j
和p
都可以使用一个名为say_hello
的新方法,它没有在类Person
的定义中定义,而是在它的扩展中定义。
instance_eval
用于定义接收对象上下文中的附加行为。
前面的例子可以重写为:
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
因为我们在j
上使用了instance_eval
,所以只有j
的行为被重新定义了,事实上我们不能在另一个实例上使用say_hello
:
r = Person.new "Robert"
r.say_hello # undefined method `say_hello' for #<Person:0x00007fac43c15b28 @name="Robert"> (NoMethodError)
这与class_eval
相反。
class_eval
允许您打开并重新定义一个类的行为,以便扩展该类的所有实例instance_eval
允许您打开和重新定义类实例的行为我认为你不应该使用它们,因为这会导致代码碎片化。
但是当你想在第三方代码上添加行为或者当你想动态添加行为时,你必须使用它们。
使用 ClassName.instance_eval 定义一个类方法(一个与类对象关联但对实例不可见的方法)。 使用 ClassName.class_eval 定义实例方法(适用于 ClassName 的所有实例的方法)。
资料来源: RubyMonk
eval 和 instance_eval 之间的主要区别之一是使用 instance_eval 您可以选择显式处理 self 的上下文。 由于 instance_eval 是 Object 上的一种方法,它的范围由您指定的 object 决定。
class_eval 比在元类(或 singleton 对象)上工作的 instance_eval 简单得多。 它在 class 上工作,就像您在文本编辑器中打开它并向其添加新的 state 或行为一样。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.