2010-05-10 28 views
0

在Ruby,的在Ruby中,如何使用coerce()實現「20-point」和「point-20」?

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 - q.x, @y - q.y) 
    end 

    def [email protected] 
    Point.new([email protected], [email protected]) 
    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) 

p p - q 
p q - p 

p p * 3 
p 5 * p 

p p - 30 
p 30 - p 

輸出:

#<Point:0x2424e54 @x=-100, @y=-100> 
#<Point:0x2424dc8 @x=20, @y=20> 
#<Point:0x2424d3c @x=-20, @y=-20> 
#<Point:0x2424cc4 @x=300, @y=300> 
#<Point:0x2424c38 @x=500, @y=500> 
#<Point:0x2424bc0 @x=70, @y=70> 
#<Point:0x2424b20 @x=70, @y=70>  <--- 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 

也就是說,該函數返回一個negated version of a - b,而不是僅僅返回a - b

回答

1

減法不是一個交換操作,所以你不能只交換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 

你需要稍微改變等方法,但我會留給你。

+1

我認爲'else'部分是錯誤的。最好它不會有幫助,在最壞的情況下它可能會導致無限循環。它'Point'類不知道如何強制'something',它應該引發'TypeError'。 – 2010-05-11 05:35:22

+0

謝謝,我完全同意。我只是將它作爲後備邏輯進行機械複製。 – 2010-05-11 10:54:04