2011-02-04 12 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

初期化子が0 にデフォルトで設定される必要があり、私は値を負の数に設定するだけでなく、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) 
    

あなたが代わりに実行時エラーを上げるのではなく、最寄りの限界に値を設定することを選択することができます。

関連する問題