【发布时间】:2026-01-03 21:55:01
【问题描述】:
在 Ruby 中,表达式 1 + Complex(1,1) 生成 Complex。
我想为用户定义的类型实现相同的功能,以便 (1 + MyType.new(...)) 产生 MyType 的值
(1 - MyType.new(...)) 类似,但减法不可交换。
这可能吗?怎么样?
【问题讨论】:
标签: ruby
在 Ruby 中,表达式 1 + Complex(1,1) 生成 Complex。
我想为用户定义的类型实现相同的功能,以便 (1 + MyType.new(...)) 产生 MyType 的值
(1 - MyType.new(...)) 类似,但减法不可交换。
这可能吗?怎么样?
【问题讨论】:
标签: ruby
你可以使用强制来处理这个问题:
class MyType
attr_reader :value
def initialize(value)
@value = value
end
def +(n)
if n.is_a?(MyType)
MyType.new(self.value + n.value)
else
@value += n
self
end
end
def coerce(other)
[MyType.new(other), self]
end
end
1 + MyType.new(12)
#=> #<MyType:0x0000561609d5d9a8 @r=13>
# or even
1 + MyType.new(12) + 3
#=> #<MyType:0x0000561bc671d170 @r=16>
当Integer 1 收到MyType 作为+ 方法的参数时,它不知道如何直接处理它,因此它会尝试通过调用coerce 将其强制为它可以理解的东西参数对象并将其自身传递给coerce 方法。
coerce 方法应始终返回包含 2 个值的 Array。然后Integer 将尝试和+ 一起使用第一个作为接收者,第二个作为参数。
所以本质上是这样的:
a = 1
b = MyType.new(12)
begin
a + b
rescue TypeError
b.coerce(a).reduce(&:+)
end
This article 对强制转换的工作原理进行了更深入的解释,并提供了何时有用的示例。
【讨论】:
1.2 + MyType.new(12) + Rational(3,4) #=> #<MyType:0x00005abcba32b230 @value=13.95>.