最近Rubyのgemを作る中で作ったクラスを対象として四則演算をoverrideするものを作った時にはまったのでそれを書く。
何にはまったのか
例えば今回は加算を例にして下記のようなクラスを例に使う。
class Hoge def initialize(value:, weight: 10) @value = value @weight = weight end def +(other) @value + other + @weight end end
動作としては下記のようになる。
> hoge = Hoge.new(value: 3) > hoge + 5 # => 18
これは何も問題はない。
ただこれを 5 + hoge
とすると下記のようになる。
> 5 + hoge TypeError: Hoge can't be coerced into Integer
Hoge
classは計算相手じゃないと。
Numeric#coerce
この時使用するのがNumericクラスに生えているcoerce
になる。
instance method Numeric#coerce (Ruby 2.4.0)
このメソッドをHoge
classで使用すればcoerceの引数には左辺の数値が入ってくれる。
これを使用して再度Hoge
classを再定義してあげる。
class Hoge def initialize(value:, weight: 10) @value = value @weight = weight end def +(other) @value + other + @weight end def coerce(other) [self, other] end end
これでHogeクラスを対象として加算で左辺、右辺どちらに数値をおいても計算が出来るようになった。
> hoge = Hoge.new(value: 5) > hoge + 5 # => 20 > 5 + hoge # => 20
余談
これはPythonだともうちょっと楽にかける。
class Hoge: def __init__(self, value, weight=10): self.value = value self.weight = weight def add(self, other): return self.value + other + self.weight def __add__(self, other): return self.add(other) def __radd__(self, other): return self.add(other)
>>> hoge = Hoge(5) >>> hoge + 5 20 >>> 5 + hoge 20