我正在尝试找出coerce
方法。当我定义*
方法和coerce
方法时。 integer * Point
触发coerce
,但"" * Point
不触发。为什么?
错误是:
coerce.rb:34:in `*': no implicit conversion of Point into Integer (TypeError) from coerce.rb:34:in `<main>'
代码是:
class Point
def initialize x,y
@x,@y = x,y
end
def * x
p "* called"
@x *= x
@y *= x
end
def coerce other
p 'coerce called'
if other.is_a? String
p "converted"
[self, other.to_i]
else
[self,other]
end
#[3,other]
end
end
p1= Point.new 1,1
p1*2
p p1
2*p1
p p1
p p1.coerce(2)
p "string test====="
"2" * p1
输出:
"* called"
#<Point:0x00564f5de89dd0 @x=2, @y=2>
"coerce called"
"* called"
#<Point:0x00564f5de89dd0 @x=4, @y=4>
"coerce called"
[#<Point:0x00564f5de89dd0 @x=4, @y=4>, 2]
"string test====="
coerce.rb:34:in `*': no implicit conversion of Point into Integer (TypeError)
from coerce.rb:34:in `<main>'
谁能告诉我为什么以及如何使"2" * p1
工作?
答案 0 :(得分:2)
这里的问题是,尽管Ruby允许您为此重新定义运算符,但这些运算符在排序方面非常特殊。
请记住该代码:
point * 2
最终被Ruby理解为:
point.send(:*, 2)
您定义的处理此特殊情况的方法Point#*
。
这段代码:
2 * point
最终被理解为:
2.send(:*, point)
到Integer#*
的位置,您对此无能为力。虽然您可以修补它,但这似乎是一个异常的坏主意。最好的办法是记录系统的工作方式并显示正确排序的示例。
在Ruby中,二元运算符的左手值基本上是负责任的,右手值只是一个乘客。