繁体   English   中英

了解 class_eval 和 instance_eval?

[英]Understanding class_eval and instance_eval?

我对何时应该使用instance_evalclass eval感到困惑。

我应该还是不应该使用它们?

简单的例子回答如何使用它们。

非常感谢。

class_evalinstance_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

jp都可以使用一个名为say_hello的新方法,它没有在类Person的定义中定义,而是在它的扩展中定义。

instance_eval

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

instance_eval

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM