Home > Software engineering >  Understanding class_eval and instance_eval?
Understanding class_eval and instance_eval?

Time:12-23

I'm confused as to when I should be using instance_eval and class eval.

I should or shouldn't use them?

Answer with simple examples on how to use them.

Thanks a lot.

CodePudding user response:

The class_eval and instance_eval are both used to reopen an object and define additional behaviour.

They follows the open/closed principle.

class_eval

class_eval is used to define additional behaviour in the context of a class.

Let's use the following Person class:

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.

instance_eval

instance_eval is used to define additional behavior in the context of a receiving object.

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:

r = Person.new "Robert"
r.say_hello # undefined method `say_hello' for #<Person:0x00007fac43c15b28 @name="Robert"> (NoMethodError)

This is the opposite of 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
  • instance_eval allows you to open and redefine the behavior of just an instance of a class

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.

CodePudding user response:

Use ClassName.instance_eval to define a class method (one associated with the class object but not visible to instances). Use ClassName.class_eval to define an instance method (one that applies to all of the instances of ClassName).

  •  Tags:  
  • ruby
  • Related