6

有没有办法让 Ruby 能够做这样的事情?

class Plane
  @moved = 0
  @x = 0
  def x+=(v) # this is error
    @x += v
    @moved += 1
  end
  def to_s
    "moved #{@moved} times, current x is #{@x}"
  end
end

plane = Plane.new
plane.x += 5
plane.x += 10
puts plane.to_s # moved 2 times, current x is 15
4

2 回答 2

6
  1. 您不能在 Ruby 中覆盖复合赋值运算符。分配在内部处理。而不是+=,您应该覆盖+. 与或plane.a += b相同。因此,您还应该覆盖in 。plane.a = plane.a + bplane.a=(plane.a.+(b))a=Plane
  2. 当你写plane.x += 5的时候,+消息是发送给plane.x,而不是plane。所以你应该重写+类中的方法x,而不是Plane
  3. 当你提到 时@variable,你应该注意电流self是什么。在class Plane; @variable; end中,@variable的是类的实例变量。这与 in 中的不同class Plane; def initialize; @variable; end; end,它是类实例的实例变量。因此,您可以将初始化部分放入initialize方法中。
  4. 应谨慎对待运算符覆盖。有时它是富有成效的和富有表现力的,但有时却不是。在这里,我认为最好fly为平面定义一个方法(例如),而不是使用某些运算符。
class Plane
  def initialize
    @x = 0
    @moved = 0
  end
  def fly(v)
    @x += v
    @moved += 1
  end
  def to_s
    "moved #{@moved} times, current x is #{@x}"
  end
end

plane = Plane.new
plane.fly(5)
plane.fly(10)
puts plane.to_s
于 2013-05-29T07:03:17.840 回答
4

运算符与+=任何方法无关,它只是语法糖,当您编写a += bRuby 解释器时将其转换a = a + ba.b += c,对于转换为 也是如此a.b = a.b + c。因此,您只需要定义方法x=x根据需要:

class Plane 
  def initialize
    @moved = 0
    @x = 0
  end

  attr_reader :x
  def x=(x)
    @x = x
    @moved += 1
  end

  def to_s
    "moved #{@moved} times, current x is #{@x}"
  end       

end

plane = Plane.new
plane.x += 5
plane.x += 10
puts plane.to_s
# => moved 2 times, current x is 15
于 2013-05-29T06:55:21.450 回答