2009-11-08 10 views
5

この質問には2つの部分があります。クラスとインスタンスの拡張

Rubyプログラミング言語の書籍には、文字列オブジェクトとクラスをモジュールで拡張する例(8.1.1節)があります。

最初の質問です。新しいメソッドでクラスを拡張し、そのクラスのオブジェクト/インスタンスを作成すると、そのメソッドにアクセスできないのはなぜですか?

irb(main):001:0> module Greeter; def ciao; "Ciao!"; end; end 
=> nil 
irb(main):002:0> String.extend(Greeter) 
=> String 
irb(main):003:0> String.ciao 
=> "Ciao!" 
irb(main):004:0> x = "foo bar" 
=> "foo bar" 
irb(main):005:0> x.ciao 
NoMethodError: undefined method `ciao' for "foo bar":String 
     from (irb):5 
     from :0 
irb(main):006:0> 

第2部Fixnumオブジェクトを拡張しようとすると、定義されていないメソッドエラーが発生します。誰かがなぜ文字列ではなくfixnumで動作するのか説明できますか?

irb(main):045:0> module Greeter; def ciao; "Ciao!"; end; end 
=> nil 
irb(main):006:0> 3.extend(Greeter) 
TypeError: can't define singleton 
     from (irb):6:in `extend_object' 
     from (irb):6:in `extend' 
     from (irb):6 

答えて

9

最初の質問。 新しいメソッドでクラスを拡張し、 のオブジェクト/インスタンスを作成してその クラスを作成すると、そのメソッドにアクセスできないのはなぜですか?

Stringクラスを拡張したので、#ciaoはクラスメソッドであり、インスタンスメソッドではありません。

String.send(:include, Greeter) 
x = "foo bar" 
x.ciao 
# => "Ciao!" 

第二の部分、私は Fixnumかのオブジェクトを拡張しようとすると、私は未定義 メソッドエラーが発生します。誰かが理由を説明できます これは文字列では動作しますが、 fixnumでは動作しませんか?

ここにはshort answerがあります。

「Fixnums、シンボル、真、ゼロ、および 偽は即時 値として実装されている。即値で、 変数は、オブジェクト自体、 ではなく、それらへの参照を保持する。

シングルトンメソッドできませんそのようなオブジェクトに対して を定義する。 同じ値の二つFixnumsが常に とFixnumかのために(例えば)ので、値「1」 インスタンス変数を同じ オブジェクトインスタンスを表すすべての間で共有されています"ones"がシステムです。これは、これがされ

「。それが不可能これらのひとつのシングルトン 方法を定義するために なり消灯もちろん、あなたがFixnumかのクラスとすべてのFixnumかのインスタンスは、ミックスインのメソッドを公開しますEXTEN /含めることができます。 まさにレール/ activesupportのは、あなたが

3.days.ago 
1.hour.from_now 
+0

あなたの答えは、なぜ(私に)説明していません。他の言語では、クラスを変更し、そのクラスタイプの新しいオブジェクトを作成すると、新しいメソッドが取得されます。私は、クラスから無効なオブジェクトへの接続があることを前提にしています。その接続がここで有効でない理由を説明できますか? – teleball

+0

あなたが私に与えた「インクルード」を調べることは助けになりました。だから今、私は拡張とインクルードの違いがあると分かっているように見え、今は何を検索するのか分かっているので、その違いを説明する記事があります:http://stackoverflow.com/questions/156362/what-ルビの包含と拡張の違い – teleball

2

obj.extend(module)を書き込むことができるようにするために行うことはobjmodule内のすべてのメソッドを追加します。あなたが目にGreeterからメソッドを追加しているString.extend(Greeter)として呼び出された場合例えば、Stringを表すClassのインスタンス。

既存のクラスにインスタンスメソッドを追加する最も簡単な方法は、クラスを再度開くことです。(真、偽とはnilだけでなく、記号、)

class String 
    include Greeter 
end 

class String 
    def ciao 
    "Ciao!" 
    end 
end 

Fixnums通常のインスタンスに異なる方法で処理されます。次の例では、同じことを行います。同じ値を持つ2つのFixnumは、常に同じオブジェクトインスタンスによって表されます。その結果、Rubyでは拡張することはできません。

あなたはもちろん例えば、他のクラスのインスタンスを拡張することができます。:最初の部分に

t = "Test" 
t.extend(Greeter) 
t.ciao 
=> "Ciao!" 
関連する問題