在Ruby中,如何使用coerce()实现“20-point”和“point-20”?
在Ruby中,操作
point - 20 # treating it as point - (20,20) 20 - point # treating it as (20,20) - point
将被实施。
但是以下代码:
class Point attr_accessor :x, :y def initialize(x,y) @x, @y = x, y end def -(q) if (q.is_a? Fixnum) return Point.new(@x - q, @y - q) end Point.new(@x - qx, @y - qy) end def -@ Point.new(-@x, -@y) end def *(c) Point.new(@x * c, @y * c) end def coerce(something) [self, something] end end p = Point.new(100,100) q = Point.new(80,80) p (-p) pp - q pq - p pp * 3 p 5 * p pp - 30 p 30 - p
输出:
# # # # # # # <--- 30 - p the same as p - 30
30 - p
实际上将被强制函数视为p - 30
。 可以使它工作吗?
我真的很惊讶-
方法不会以这种方式强制论证:
class Fixnum def -(something) if (/* something is unknown class */) a, b = something.coerce(self) return -(a - b) # because we are doing a - b but we wanted b - a, so it is negated end end end
也就是说,该函数返回a negated version of a - b
的negated version of a - b
而不是仅返回a - b
。
减法不是一个可交换的操作,所以你不能只是在你的coerce
交换操作数并期望它能够工作。 coerce(something)
应该返回[something_equivalent, self]
。 所以,在你的情况下,我认为你应该像这样编写你的Point#coerce
:
def coerce(something) if something.is_a?(Fixnum) [Point.new(something, something), self] else [self, something] end end
你需要稍微改变其他方法,但我会把它留给你。