加上等于红宝石发送消息

时间:2013-08-12 09:42:21

标签: ruby

我熟悉ruby发送方法,但由于某种原因,我不能做这样的事情

a = 4
a.send(:+=, 1)

出于某种原因,这不起作用。然后我尝试了类似

的东西
a.send(:=, a.send(:+, 1))

但这也行不通。通过'发送'解雇加上等于的正确方法是什么?

5 个答案:

答案 0 :(得分:6)

我认为基本选项只是:

a = a.send(:+, 1)

这是因为send用于对象的消息。赋值修改变量,而不是对象。


可以通过一些元编程直接分配给变量,但代码是复杂的,到目前为止我能找到的最好的是:

a = 1
var_name = :a
eval "#{var_name} = #{var_name}.send(:+, 1)"
puts a  # 2

或使用实例变量:

@a = 2
var_name = :@a
instance_variable_set( var_name, instance_variable_get( var_name ).send(:+, 1) )
puts @a  # 3

答案 1 :(得分:1)

见下文:

p 4.respond_to?(:"+=") #  false
p 4.respond_to?(:"=")  #  false
p 4.respond_to?(:"+")  #  true

a+=1a = a+1的句法糖。但是没有直接的方法+==是赋值运算符,也不是方法。另一方面,Object#send将方法名称作为其参数。因此,您的代码将无法正常工作。

答案 2 :(得分:0)

这是因为Ruby没有=方法。在Ruby =中,它不像在C / C ++中那样工作,而是将新的对象引用分配给变量,而不是为变量赋值。

答案 3 :(得分:0)

您无法在a上调用方法,因为a不是对象,它是变量,变量不是Ruby中的对象。您在4上调用方法,但4不是您要修改的内容,a是。这是不可能的。

注意:当然可以定义一个名为=+=的方法并调用它,但当然这些方法只存在于对象上,而不是变量。

class Fixnum
  define_method(:'+=') do |n| self + n end
end

a = 4

a.send(:'+=', 1)
# => 5

a
# => 4

答案 4 :(得分:0)

这可能会有点遗漏标记,但是我尝试这样做,其中a实际上是在对象上动态调用的方法。例如,对于added_count,使用updated_countImporter之类的属性,我写了以下内容

class Importer
  attr_accessor :added_count, :updated_count

  def increment(method)
    send("#{method}=", (send(method) + 1))
  end

end

所以我可以使用importer.increment(:added_count)importer.increment(:updated_count)

现在,如果您只有这两个不同的计数器,这似乎很愚蠢,但是在某些情况下,我们有六个或更多的计数器,并且attr的递增条件不同,因此可以方便使用。