2011-02-04 3 views
2

Как я могу ограничить переменную, которая принадлежит новому классу < Fixnum, между 0 и 255? Или если я не могу создать ограничение в подклассе Fixnim, как написать свой собственный класс с лимитом?Как ограничить переменную в рубине?

+0

Написав свой собственный класс –

+2

суб-причислять Fixnum не рекомендуется, см: http://stackoverflow.com/questions/1095789/sub-classing-fixnum-in-ruby – tokland

ответ

2

Напишите не наследуемый класс и используйте method_missing для вызова всех функций из переменной экземпляра, они ограничивают возвращаемое значение.

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 
+1

Initializer должен по умолчанию 0. I будет утверждать, что добавление от 300 до 103 должно генерировать исключение, а также устанавливать отрицательное число в значение. – DJTripleThreat

+0

Можно ли сравнить int с другим номером и как? – golovanovski

+0

int == 0 # false – golovanovski

4
  1. Не заставляйте номер класса, сделать доступ к этому номеру ограничивается в рамках вашего класса через присваиватель.
  2. Внутри вашего класса никогда не устанавливайте переменную экземпляра, кроме как через метод setter.
  3. Если вам нужно сделать, это часто делают вспомогательный метод для этого:

    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) 
    

Вы можете альтернативно выбрать, чтобы установить значение до ближайшего предела вместо повышения ошибки во время выполнения.

Смежные вопросы