我正在熟悉 ruby 发送方法,但由于某种原因,我不能做这样的事情
a = 4
a.send(:+=, 1)
由于某种原因,这不起作用。然后我尝试了类似的东西
a.send(:=, a.send(:+, 1))
但这也行不通。通过“发送”触发加号等于的正确方法是什么?
我正在熟悉 ruby 发送方法,但由于某种原因,我不能做这样的事情
a = 4
a.send(:+=, 1)
由于某种原因,这不起作用。然后我尝试了类似的东西
a.send(:=, a.send(:+, 1))
但这也行不通。通过“发送”触发加号等于的正确方法是什么?
我认为基本选项只有:
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
见下文:
p 4.respond_to?(:"+=") # false
p 4.respond_to?(:"=") # false
p 4.respond_to?(:"+") # true
a+=1
是 的语法糖a = a+1
。但是没有直接的方法+=
。=
是赋值运算符,而不是方法。另一方面Object#send
,将方法名称作为其参数。因此,您的代码将无法按照您正在寻找的方式工作。
您不能在 上调用方法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
这是因为 Ruby 没有=
方法。在 Ruby=
中不像在 C/C++ 中那样工作,而是将新对象引用分配给变量,而不是为变量分配新值。
这可能有点偏离目标,但我试图做到这一点,a
实际上是在对象上动态调用的方法。例如,使用added_count
和updated_count
for这样的属性,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 递增的不同条件,因此它很方便。