Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between "__send__" and "instance_variable_get / instance_variable_set" methods?

All is stated in the question. Both of these methods can access (read/write) instance variables by using their code name :

__send__


instance_variable_set
instance_variable_get

Could someone explain it by examples ?

Metaprogramming is sometimes melting our brain when we explore it with abstraction.

=== EDIT ===

Ok I make a resume of the answers as an example for later use if my brain is melting again.

Class declaration :

class Person

  attr_accessor :first_name, :last_name

  def initialize(first_name, last_name)
    @first_name = first_name
    @last_name = last_name
  end

  def full_name
    @first_name + ' ' + @last_name
  end

end

Initialization :

actor = Person.new('Donald', "Duck")
=> #<Person:0xa245554 @first_name="Donald", @last_name="Duck">

usage of send (read) :

actor.send('first_name')
=> "Donald"

actor.send(:first_name)
=> "Donald"

actor.send("last_name")
=> "Duck"

actor.send(:last_name)
=> "Duck"

actor.send('full_name')
=> "Donald Duck"

actor.send(:full_name)
=> "Donald Duck"

usage of instance_variable_get (read)

actor.instance_variable_get('@first_name')
=> "Donald"

actor.instance_variable_get(:@first_name)
=> "Donald"

actor.instance_variable_get('@last_name')
=> "Duck"

actor.instance_variable_get(:@last_name)
=> "Duck"

usage of send (write) :

actor.send('first_name=', 'Daisy')

actor.send('full_name')
=> "Daisy Duck"

actor.send(:first_name=, "Fifi")

actor.send("full_name")
=> "Fifi Duck"

usage of instance_variable_set (write)

actor.instance_variable_set('@first_name', 'Pluto')
actor.send("full_name")
=> "Pluto Duck"

actor.instance_variable_set(:@last_name, 'Dog')
actor.send(:full_name)
=> "Pluto Dog"

INCORRECT usage of instance_variable_get (read)

actor.instance_variable_get('full_name')
#NameError: `full_name' is not allowed as an instance variable name

actor.instance_variable_get('last_name')
#NameError: `last_name' is not allowed as an instance variable name

I was geting confuse with Rails ActiveRecord and its Associations.

Thanks for the answers !

like image 747
Douglas Avatar asked Jun 22 '26 22:06

Douglas


2 Answers

__send__ methods invokes method which are defined in your class, if the method is not defined then you cannot use send method, but instance_variable_get and set methods changes the value of the instance variable without the need for any encapsulating methods (like getters or setters).

__send__ is used if you want to invoke a method identified by the symbol and passing any argument if needed.

e.g.

class Test
  def sayHello(*args)
    "Hello " + args.join(' ')
  end
end
k = Test.new
k.send :sayHello, "readers"   #=> "Hello readers"

instance_variable_get Returns the value of the given instance variable, or nil if the instance variable is not set. Use this method without the need for encapsulation

e.g

class Test
  def initialize(p1)
    @a = p1
  end
end
test = Test.new('animal')
test.instance_variable_get(:@a)    #=> "animal"

instance_variable_set used to set the value for an instance variable without the need for encapsulating methods. e.g

class Test
  def initialize(p1)
    @a = p1
  end
end
test = Test.new('animal')
test.instance_variable_set(:@a, 'animal')
like image 161
Sajan Chandran Avatar answered Jun 25 '26 12:06

Sajan Chandran


__send__ allows you to call a method by name/symbol,
instance_variable_* allows you to set/get instance variables.

like image 32
deceze Avatar answered Jun 25 '26 12:06

deceze



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!