2011-04-04 7 views
2

私はKlassの作成されたオブジェクトのコレクションを維持したいと思います。 newスルー:initializeスルー:まず作成されたオブジェクトのコレクションを維持するための最良の方法

:セカンド

class Klass 
    @@objs = [] 

    def initialize *args 
    # ... do regular initialization ... 
    Klass.send :add, self 
    end 

    class << self 
    def objs 
     @@objs 
    end 

    private 

    def add obj 
     @@objs << obj 
    end 
    end 
end 

class Klass 
    @@objs = [] 

    class << self 
    def objs 
     @@objs 
    end 

    alias_method :old_new, :new # never thought someday I'd name something as "old_new"! 
    private :old_new 

    def new *args 
     obj = super 
     @@objs << obj 
     obj 
    end 
    end 
end 

テスト:私は2つの方法イム心持って

a = Klass.new 
b = Klass.new 
puts a.inspect   #=> #<Klass:0xb7786ba0> 
puts b.inspect   #=> #<Klass:0xb7786b78> 
puts Klass.objs.inspect #=> [#<Klass:0xb7786ba0>, #<Klass:0xb7786b78>] 

両作品を、私は傾向があります"追加"のために第2の方法を好む:プライベートでなければならず、私は "Klass.send" 。最善の方法は何ですか?他の(より良い)方法がありますか?

答えて

1

通常のコンストラクタではただ<<だけでいいですか?シンプルなコードで、まれに良い考えではないnewを再定義する必要はありません。

+0

を行うことができます!私は盲目でした! –

3

サインは、新しいオブジェクトが作成されるたびに呼び出された初期化し、私はこの事実を利用し、ちょうど行うだろう:new普段呼んとしてあなたalias_methodprivateは、必要なかったこと

def initialize *args 
    # ... do regular initialization ... 
    @@objs << self 
end 
+0

ヤクブは本質的に同じと言った。とにかくありがとうございました! :) –

1

注意Class#newです。また、クラス変数を使用する理由もありません(マスタークラスのサブクラスの作成を追跡しない限り)。良くない場合、これは、同じようにうまく機能:

class Foo 
    class << self; attr_reader :objs; end 
    def self.new(*a,&b) 
    super.tap{|o| (@objs||=[]) << o} 
    end 
end 
class Bar < Foo; end 
2.times{ Foo.new } 
3.times{ Bar.new } 

p Foo.objs 
#=> [#<Foo:0x2bb6260>, #<Foo:0x2ba2400>] 

p Bar.objs 
#=> [#<Bar:0x2ce6000>, #<Bar:0x2baf4e0>, #<Bar:0x2b94f40>] 

あなたの初期化子で配列に追加に対するこの手法の利点は、あなたのサブクラスのinitializesuperを呼び出すために覚えておく必要がないということです。実際には、サブクラスでinitializeと定義する必要はありません。

+0

+1クラス 'new'について私の目を開き、' tap'を使うために(先ほどの 'tap 'を知っていたら、私は2番目の例で使用します)。しかし、 'initialize'(とクラス変数の使用)の' '' 'は私が探していたものです。私は、クラスインスタンス変数とそのクラスの利点についてはクラス変数について知っていますが、この場合はクラス変数を使用します。 –

+0

@SonySantos問題はありません。お探しの答えがありがとうございます。私はあなたが私の答えに切り替えるように動こうとしていたからではなく、わずかに異なるニーズを持つ他のユーザーがこの質問を見つける別の答えを持つように、この回答を追加しました(あなたはすでに回答を受け入れていました)。ハッピールビーコーディング! :) – Phrogz

+0

2番目の例で 'obj = super'の代わりに' obj = old_new * args'を行うという私の意図がわかりました。私はなぜそれが働いたのか分かりません。インスタンスメソッドの中から 'super'を呼び出すと、現在のオブジェクトの親クラス、つまり' object.class.superclass'というメッセージを送信して、同じ名前のインスタンスメソッドを実行します。クラスメソッドから 'super'を呼び出すと、現在のクラスの親クラスのメッセージ、つまり' Klass.class.superclass'というインスタンスとして 'インスタンスメソッドとして新しい。 –

0

またありがとう

class IndividualKlass 
end 

class KlassCreator 
    def initialize(individual_klass) 
    @individual_klass = individual_klass 
    @objects = [] 
    end 

    def create_object 
    object = @individual_klass.new 
    @objects << object 
    object 
    end 
end 

klass_creator = KlassCreator.new(IndividualKlass) 
IndividualKlass = nil # Or remove_const or something 

object = klass_creator.create_object 
+0

非常に面白い!:) –

関連する問題