简体   繁体   English

了解 class_eval 和 instance_eval?

[英]Understanding class_eval and instance_eval?

I'm confused as to when I should be using instance_eval and class eval .我对何时应该使用instance_evalclass 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_evalinstance_eval都用于重新打开对象并定义其他行为。

They follows the open/closed principle .他们遵循开放/封闭原则

class_eval类评估

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. jp都可以使用一个名为say_hello的新方法,它没有在类Person的定义中定义,而是在它的扩展中定义。

instance_eval instance_eval

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相反。

Summary概括

  • 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允许您打开和重新定义类实例的行为

You should or shouldn't use them?你应该还是不应该使用它们?

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

instance_eval instance_eval

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 类评估

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.

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