0

在 Ruby 中,似乎可以通过以下方式完成很多 coerce() 帮助

def coerce(something)
  [self, something]
end

也就是说,当

3 + rational

需要,Fixnum3不知道如何处理添加一个 Rational,所以它通过调用rational.coerce(3) 向 Rational#coerce 寻求帮助,这个 coerce 实例方法将告诉调用者:

# I know how to handle rational + something, so I will return you the following:
[self, something]
# so that now you can invoke + on me, and I will deal with Fixnum to get an answer

那么如果大多数运营商都可以使用这种方法,但在 (a - b) != (b - a) 的情况下却不能使用呢?coerce() 可以知道它是哪个运算符,并且只处理那些特殊情况,同时只使用简单的 [self, something] 来处理 (a op b) == (b op a) 的所有其他情况吗?(op 是运算符)。

4

2 回答 2

1

关键coerce是不知道您要执行什么操作。它的目的是使论点和self共同点。此外,相同的运算符在某些类中可以是可交换的,而在其他类中则不能(例如Numeric#+and Array#+),因此您的基于交换性的小型coerce利用确实不会得到回报。

您应该创建一个新类(例如,例如),而不是强迫您coerce做它不打算做的事情,并使用它来接口标量值与您的:ScalarPointPoint

class ScalarPoint
  attr_reader :val

  def initialize(val)
    @val = val
  end

  def +(arg)
    case arg
    when Point:
      Point.new(@val + arg.x, @val + arg.y)
    when ScalarPoint:
      ScalarPoint.new(arg.val + @val)
    else
      raise "Unknown operand!"
    end
  end

  # define other operators, such as * etc

  def coerce(arg)
    return [ScalarPoint.new(arg), self] if arg.is_a?(Numeric)
    raise "Can't handle"
  end
end

class Point
  def coerce(arg)
    [ScalarPoint.new(arg), self] if arg.is_a?(Numeric)
    raise "Can't handle"
  end
end

等(注意:代码未经测试)

于 2010-05-11T12:53:09.690 回答
1

这个问题的答案是您可以通过查看回溯来了解操作员,但您不应该这样做。

Ruby 的强制机制不是这样设计的。正如我在您之前的问题中回答的那样,coerce应该返回两个等效的值[a, b],这样a.send(operator, b)无论运算符如何都可以工作。

于 2010-05-11T05:30:24.407 回答