“__send__”和“instance_variable_get / instance_variable_set”方法有什么区别?

时间:2013-01-23 10:48:57

标签: ruby metaprogramming instance-variables

所有问题都在问题中说明。 这两种方法都可以使用它们的代码名称来访问(读/写)实例变量:

__send__


instance_variable_set
instance_variable_get

有人可以通过例子来解释吗?

当我们用抽象来探索时,元编程有时会使我们的大脑融化。

===编辑===

好的,如果我的大脑再次融化,我会将答案的简历作为一个例子供以后使用。

班级声明

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

初始化

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

使用发送(读取):

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"

使用instance_variable_get (阅读)

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"

使用发送(写):

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

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

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

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

使用instance_variable_set (写)

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使用instance_variable_get (读取)

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

我对Rails ActiveRecord及其协会感到困惑。

感谢您的回答!

2 个答案:

答案 0 :(得分:2)

__send__允许您通过名称/符号调用方法 instance_variable_*允许您设置/获取实例变量

答案 1 :(得分:2)

__send__方法调用类中定义的方法,如果未定义方法,则不能使用send方法,但instance_variable_getset方法会更改实例变量的值,不需要任何封装方法(如getter或setter)。

如果要调用符号标识的方法并在需要时传递任何参数,则使用

__send__

e.g。

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

instance_variable_get返回给定实例变量的值,如果未设置实例变量,则返回nil。使用此方法而无需封装

例如

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

instance_variable_set用于设置实例变量的值,而无需封装方法。 e.g

class Test
  def initialize(p1)
    @a = p1
  end
end
test = Test.new('animal')
test.instance_variable_set(:@a, 'animal')