为什么我使用“” * Point时不触发强制

时间:2019-05-13 07:01:40

标签: ruby

我正在尝试找出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工作?

1 个答案:

答案 0 :(得分:2)

这里的问题是,尽管Ruby允许您为此重新定义运算符,但这些运算符在排序方面非常特殊。

请记住该代码:

point * 2

最终被Ruby理解为:

point.send(:*, 2)

您定义的处理此特殊情况的方法Point#*

这段代码:

2 * point

最终被理解为:

2.send(:*, point)

Integer#*的位置,您对此无能为力。虽然您可以修补它,但这似乎是一个异常的坏主意。最好的办法是记录系统的工作方式并显示正确排序的示例。

在Ruby中,二元运算符的左手值基本上是负责任的,右手值只是一个乘客。