Как ограничить переменную в рубине? - PullRequest
2 голосов
/ 04 февраля 2011

Как я могу ограничить переменную, которая принадлежит новому классу

Ответы [ 2 ]

4 голосов
/ 05 февраля 2011
  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)
    

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

2 голосов
/ 04 февраля 2011

Напишите не унаследованный класс и используйте 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...