5

それらのオブジェクトを定義するクラス内で、特定のクラスのオブジェクトのインスタンスの数を保持しようとしています。

まず第一に、私はコード リフレクションと ObjectSpace.each_object を認識していますが、リフレクションを使用せず、クラス自体がそれ自体を「管理」できるようにしたいと考えています。

私が見回したところ、見つかったすべてのソリューションは、たとえば、この質問に対する受け入れられた回答のように、クラス定義で @@class_variables を使用しているようです: Rubyでクラスインスタンスを取得する方法?

しかし、読み続けていると、ルビーのクラス変数が状況によっては非常に悪い動作をすることがあることがわかりました...最大の理由は次のとおりです。

プログラムのトップレベルで定義されたクラス変数は、すべてのクラスに継承されます。グローバル変数のように動作します。

ソースと詳細情報はこちら: http://ruby.runpaint.org/variables#class

それで、クラス変数の代わりにクラスインスタンス変数を使用して、インスタンス化されたオブジェクトの数を内部に格納するクラスをコーディングしようとしましたが、どうやらうまくいくようですが、この「深い」言語についてまだ学んでいるので私が書いたコードが正しいかどうか、および/または意味があるかどうかをお尋ねしたいトピック:

class Pizza
  @orders = 0
  def self.new
    @orders += 1
  end
  def self.total_orders
    @orders
  end
end

new_pizza = Pizza.new #=> 1
special_pizza = Pizza.new #=> 2
fav_pizza = Pizza.new #=> 3

私の疑問の 1 つは、Pizza.new メソッドをオーバーライドすると、元の .new メソッドのいくつかの重要な機能が「削除」されることですか? (元の .new メソッドは何を提供しますか?? リフレクションを使用してメソッド コードを「検査」するにはどうすればよいですか?) 他に間違っていること、または私のアプローチで完全に間違っていることとその理由は?

ありがとう

編集:この重要なビットを追加するのを忘れました:

範囲をより適切に制限する方法として、Pizza クラスがオブジェクトのインスタンス化時にのみカウントできるようにし、コード内でいつでもアクセスできる @instance クラス変数にセッター メソッドを持たないようにしたいと考えています。 (Pizza.count = 1000)。そのため、「new」をオーバーライドしようとしていました。

これは、自分のアプローチが正しい方向に進んでいるのか、または単にこれらの言語メカニズムにあまり依存するのをやめて、オブジェクトがPizza クラスが ObjectSpace に入りました。

私は、言語機能を使用してこれを取得するための、よりエレガントで肥大化していない方法を探しています..

どちらの場合でも、助けていただければ幸いです..

再度、感謝します。

4

2 に答える 2

9

new をオーバーライドする必要はありません。これを試して:

class Pizza
  @count = 0
  class << self
    attr_accessor :count
  end

  def initialize
    self.class.count += 1
  end
end

Pizza.new
Pizza.new
puts Pizza.count

ピザがガベージコレクションされているときは下がらず、ピザが編集Pizza.countされているときは上がらないことに注意してください。dup

他の質問に答えるには: メソッドを調べる方法はわかりませんがnew、おそらく C で書かれているので、Ruby のソース コードを調べる必要があります。基本的にはこれでいいと思います。

def new(*args, &block)
  o = allocate
  o.initialize(*args, &block)
  o
end

superある時点で呼び出している限り、おそらく new をオーバーライドすることで逃げることができます。(これが良い考えだとは言いませんが、例えば:

class Foo
  def self.new
    # do whatever stuff you want here
    super
  end
end

)

于 2012-10-15T18:31:41.000 に答える
1

あなたが正しいです。クラス変数を使用することは、時々気が遠くなるようなものです。継承されるかどうかなどを常に忘れます。

あなたのアプローチは正しいですが...

代わりにnew実装をオーバーライドしないでください。initializeすべてのオブジェクトの初期化プロセス中に呼び出されます。ここのドキュメントを参照してください: http://apidock.com/ruby/v1_9_3_125/Class/new

于 2012-10-15T09:42:51.583 に答える