7

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

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

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

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

但这也行不通。通过“发送”触发加号等于的正确方法是什么?

4

5 回答 5

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
于 2013-08-12T09:52:13.960 回答
1

见下文:

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

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

于 2013-08-12T09:57:51.433 回答
0

您不能在 上调用方法a,因为a它不是对象,而是变量,而变量在 Ruby 中也不是对象。您正在调用 上的方法4,但4不是您要修改的东西a。这是不可能的。

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

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

a = 4

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

a
# => 4
于 2013-08-12T13:49:36.053 回答
0

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

于 2013-08-12T09:57:32.353 回答
0

这可能有点偏离目标,但我试图做到这一点,a实际上是在对象上动态调用的方法。例如,使用added_countupdated_countfor这样的属性,Importer我编写了以下内容

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)

现在,如果您只有这 2 个不同的计数器,这可能看起来很愚蠢,但在某些情况下,我们有六个或更多的计数器以及 attr 递增的不同条件,因此它很方便。

于 2018-10-11T20:00:24.203 回答