2

How can I limit a variable that belongs to new Class < Fixnum, between 0 and 255? Or if I can't create a limit in subclass of Fixnim how to write my own class with limit?

  • 2
    sub-classing Fixnum is not recommended, see: http://stackoverflow.com/questions/1095789/sub-classing-fixnum-in-ruby – tokland Feb 04 '11 at 18:49

2 Answers2

4
  1. Don't make the number a class, make access to that number limited as part of your class via a setter method.
  2. Within your class never set the instance variable except via the setter method.
  3. If you need to do this often, make a helper method for it:

    class Module
      def limited_value( name, range=0..100 )
        attr_reader name
        define_method(:"#{name}=") do |new_value|
          if range.include?( new_value )
            instance_variable_set :"@#{name}", new_value
          else
            raise "Out of Bounds"
          end
        end
      end
    end
    
    class Foo
      limited_value :bar, 0..255
    end
    
    f = Foo.new
    p f.bar      #=> nil
    f.bar = 10
    p f.bar      #=> 10
    f.bar = 300
    #=> tmp.rb:8:in `block in limited_value': Out of Bounds (RuntimeError)
    

You could alternatively choose to set the value to the nearest limit instead of raising a runtime error.

Phrogz
  • 296,393
  • 112
  • 651
  • 745
2

Write a non inherited class and use method_missing to call all functions from a instance variable, them, limit the return value.

class MyNum
  instance_methods.each {|m| eval("undef " << m) }
  def initialize(fixnum)
    @num = fixnum
  end
  def method_missing(name, *args, &blk)
    ret = @num.__send__(name, *args, &blk)
    Numeric === ret ? MyNum.new([[ret, 0].max, 255].min) : ret
  rescue NoMethodError
    super
  end
  def inspect
    "MyNum(#{@num.inspect})"
  end
  def class
    MyNum
  end
end

int = MyNum.new(50) # => MyNum(50)
int += 52 # => MyNum(102)
int.succ # => MyNum(103)
int + 300 # => MyNum(255)
int = -int # => MyNum(0)
int.zero? # => true
int == 0 # => true
Guilherme Bernal
  • 8,183
  • 25
  • 43