2009-07-08 13 views
7

Fixnum、FloatまたはIntegerを直接サブクラス化することは想定されていないことを理解しています。#新しいメソッドがないためです。 DelegateClassの使用はうまくいくようですが、これが最善の方法ですか?誰もが、これらのクラスの背後にある理由が何か新しいことが分かっていないかどうか知っていますか?サブクラス化ルビのFixnum

私はFixnumかのように動作しますが、いくつかの余分なメソッドを持つクラスを必要とする、と私は例えば、クラス内からselfを通じてその値を参照できるようにしたいと思います:

class Foo < Fixnum 
    def initialize value 
    super value 
    end 

    def increment 
    self + 1 
    end 
end 

Foo.new(5).increment + 4 # => 10 
+0

あなたが実際にやっていること(最終目標)を教えてください。それを実行するための最善の方法を教えてあげます。私はここでサブクラスが適切だとは思わない。 –

+0

が更新しました。 – cloudhead

答えて

17

class MyNum 
    def initialize(number) 
    @number = number 
    end 

    def method_missing(name, *args, &blk) 
    ret = @number.send(name, *args, &blk) 
    ret.is_a?(Numeric) ? MyNum.new(ret) : ret 
    end 
end 

次に、あなたがMyNumに好きな方法で追加することができますが、これらの方法で@number上で動作する必要があります、というよりスーパーを直接呼び出すことができます。

+0

うーん。しかし、MyNum.new(2)+ MyNum.new(3)を実行した場合、MyNumインスタンスの代わりにFixnumを返さないでしょうか?私はあなたがMyNum.newで@ number.sendを折り返す必要があると思う。 –

+0

元の応答が数値だった場合にMyNumを返すように私の答えを更新した。 –

+0

MyNumは、MyNum.new(5)== 5 AND 5 == MyNum.new(5)となるように実装できますか? – rcrogers

2

FixNum自体を拡張できませんか?様...ワードの下位ビットのいくつかを使用して

class Fixnum 
    def even? 
    self % 2 == 0 
    end 
end 

42.even? 
+1

私はできますが、私はむしろそうしたくありません。また、Fixnumには#newがなく、#initializeに機能を追加する必要があります。 – cloudhead

+1

猿のパッチは慎重に使用する必要があります。特定のユースケースのためだけにRubyコアクラスを汚染すると、危険な可能性があります。 –

4

IIRC、即値としてルビーを記憶するFixnumsの主な実装は、Fixnumかの代わりに、ヒープ上のオブジェクトへのポインタとしてタグ付けします。そのため、32ビットマシンでは、Fixnumは完全な語ではなく29ビット(またはそれが何であれ)にすぎません。

したがって、Fixnumの1つの「インスタンス」にメソッドを追加することはできず、サブクラス化することはできません。

"Fixnumのような"クラスを使い果たしてしまった場合は、おそらくFixnumインスタンス変数を持つクラスを作成し、メソッド呼び出しを適切に転送する必要があります。

あなたはかなり簡単に素早く転送の実装を自分で設定することができ
+0

ああそうです。サブクラス化できる他のクラスはありますか?数値は#newを持っていますが、引数をとらないので、抽象クラスだと思います。 – cloudhead

+0

Hmm。私はしばらくRubyに触れていないし、数値クラスツリーのレイアウト方法を正確には思い出せない。 –

+0

明らかに唯一の候補はBigDecimalです。 –

関連する問題