В RUBY, может ли метод Coerce () знать, какой оператор именно это требует помощи, чтобы помочь?
-
25-09-2019 - |
Вопрос
В Руби, похоже, что много помощи () может быть сделано
def coerce(something)
[self, something]
end
Это, когда
3 + rational
нужен, fixnum 3
Не знает, как обрабатывать добавление рационального, поэтому он просит Rational # Coerce для получения справки, вызывая Rational.coerce (3), и этот метод экземпляра 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) Ситуация? Может принуждать () знать, какой оператор имеется, и просто обрабатывать эти особые случаи, одновременно используя простое [я, что-то], чтобы обрабатывать все остальные случаи, где (OP b) == (b op a)? (ОП является оператором).
Решение
Точка coerce
это не знать, какую операцию вы пытаетесь выполнить. Его цель - принести аргумент и self
на общую почву. Кроме того, такие же операторы могут быть коммутативными в определенных классах, а не в других (Numeric#+
а также Array#+
, Например), так что ваша небольшая коммутативная coerce
Эксплей действительно не окупится.
Вместо того, чтобы толкать ваш coerce
делать то, что он не предназначен, вы должны создать новый класс вместо этого (например, ScalarPoint
, Например) и используйте его для интерфейса скалярных значений с вашим Point
:
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
и т. д. (NB: код не тестирован)
Другие советы
Ответ на этот вопрос в том, что вы могу знать оператор, глядя на трассировку, но вам не должен сделай это.
Это не то, как был разработан механизм принудительного рубина. Как я отвечал в Ваш предыдущий вопрос, coerce
следует вернуть два эквивалентных значения [a, b]
Такое это a.send(operator, b)
Будет работать, независимо от оператора.