问题
Is there a way to make Ruby able to do something like this?
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
回答1:
The +=
operator is not associated to any method, it is just syntactic sugar, when you write a += b
the Ruby interpreter transform it to a = a + b
, the same is for a.b += c
that is transformed to a.b = a.b + c
. Thus you just have to define the methods x=
and x
as you need:
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
回答2:
- You cannot override compound assignment operators in Ruby. The assignments are handled internally. Instead of
+=
, you should override+
.plane.a += b
is the same asplane.a = plane.a + b
orplane.a=(plane.a.+(b))
. Thus you should also overridea=
inPlane
. - When you write
plane.x += 5
, the+
message is send toplane.x
, notplane
. So you should override+
method in the class ofx
, notPlane
. - When you refer to
@variable
, you should pay attention to what the currentself
is. Inclass Plane; @variable; end
,@variable
refers to the instance variable of the class. That's different with the one inclass Plane; def initialize; @variable; end; end
, which is instance variable of the class's instances. So you can put the initialization part intoinitialize
method. - Operator overriding should be treated carefully. Sometimes it is productive and expressive, but sometimes it isn't. Here I think it's better to define a method (e.g.
fly
) for plane rather than using some operator.
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
来源:https://stackoverflow.com/questions/16805933/ruby-method-for