最大値で値を制限できる数値クラスの作成

久々の日記です。最大値を制限できる数値クラスが作りたいなと思ってたらものっそいキモイのが出来上がったので公開。
値を直接変更できないのでvalue=というメソッドを使用することにしましたが、それ以外は普通の数値として扱えるはず。

require "delegate"

class SizedNumeric < DelegateClass(Numeric)
  attr_accessor :max
  
  def initialize max
    @max = max
    super 0
  end
  
  def value= value
    raise RangeError unless (0..max).include? value
    __setobj__ value
  end
  
  def coerce other
    [other, __getobj__]
  end
end

追記

「数値クラスはimmutable」という突っ込みに対して修正してみましたがこれはコレでキモイというか不便でした。

class SizedNumeric < DelegateClass(Numeric)
  attr_accessor :max
  
  def initialize max, value = 0
    raise RangeError unless (0..max).include? value
    
    @max = max
    super value
  end
  
  def coerce other
    [other, __getobj__]
  end
  
  def method_missing *args
    SizedNumeric.new @max, super
  end
end
snum = SizedNumeric.new 5, 0 #=> 0
snum += 5                    #=> 5
snum+1                       # RangeError

足し算しただけでRangeErrorてどうなの。
「上限のある数値」はNumericじゃないのでmutable、と考えて名称を変更したほうが良さそうな予感。