クラスのすべてのオブジェクトを追跡する


9

私はオブジェクト指向プログラミングが初めてなので、この問題に遭遇し続けます。(私はJavaでプログラミングしています)このような基本的な問題のように思われるので、私はこれについて尋ねるのに少し消極的でしたが、それに関する情報や質問についてここで見つけることはできません。私が(非常に基本的なレベルで)読んだ教科書は、この問題に触れています:

多くの場合、作成されたクラスのすべてのオブジェクトを追跡して、さまざまな目的でそれらを反復処理する必要があります。彼らは私が現在プログラムを書いているように、多くのオブジェクトは他のオブジェクトからのみ参照されます。つまり、それらすべてを参照する配列やコレクションはありません。

これはOOPの非常に基本的な必要性のように思われるので、これを行うにはかなり制度化された簡単な方法があるはずだと思います。クラスのすべてのオブジェクトの個別のリストを保持することは通常の習慣ですか?

静的配列または静的コレクションについて考えました。コンストラクターを介して、作成されたすべての新しいオブジェクトが追加されます。ただし、コンストラクターは継承されないため、これはサブクラスでは機能しません。

この質問には1つの簡単な答えがないかもしれません。誰かがこの問題について少し教えてくれることを願っています。ここで中心的な知識が不足しているような気がします。


5
追跡対象とトラッカーのより具体的な例が役立つ場合があります。この問題は、コンテキスト、使用方法などに応じて、さまざまな方法で処理されます。
JustinC 2013年

2
私はあなたが間違った目的から問題に近づいているかもしれないと思います。特定のクラスのすべてのインスタンスのリストが必要になることはあまり一般的ではありません。リストを1つ持つと、あらゆる種類の設計上の問題が発生します(まったく関係のないコンテキストで作成されたインスタンスでさえ、このリストを通じて互いに依存するため)。
tdammers 2013年

1
「さまざまな目的でそれらを繰り返す」...など...?一般に、オブジェクトには「所有者」が1つあり(正式な用語ではなく、プログラムのセマンティクスについての単なる説明)、オブジェクトを「さまざまな目的」で使用することは他人にはできません。
AakashM 2013年

回答:


8

クラスのすべてのインスタンスのリストを保持する必要がある理由がわかりません。

これらのオブジェクトは決して破棄されないため、メモリリークが発生します。他のクラスが参照しない場合でもリストはそれらを参照しているためです。

しかし、あなたが本当にそのルートをたどりたければ:

  1. Factoryパターンを使用します。クラスをインスタンス化してオブジェクトを返すメソッドを持つファクトリクラス。このようにして、インスタンス化を制御するための集中化されたポイントがあります。
  2. シングルトンパターンを使用して、インスタンスを保持するリストを保持します。
  3. ファクトリーに、特定のタイプの各オブジェクトを作成した後でリストに入れさせます。

ちなみに、コンストラクタは継承されます。


もちろん、追跡するインスタンスのリストからインスタンスを削除する「dispose」メソッドをファクトリに与えることができます。しかし、それを明示的に呼び出す方法はありません。または、インスタンスに、ファクトリーでdisposeメソッドをトリガーするdisposeメソッドを指定します。これには同じ欠点がありますが、ユーザーに近いほど、実際に呼び出される可能性が高くなります。
2013年

@jwentingもちろんそうです。しかし、それはクラスとファクトリーの間に醜く不必要な依存関係を作成します。クラスは、クラスを作成するファクトリについて何も知らないはずです。
TulainsCórdova2013

したがって、オブジェクトにファクトリーに登録するように指示するのではなく、ファクトリーに作成内容を追跡させます...
jwenting

シングルトンは技術的に私が推測するすべてのインスタンスを保持します。1つの単一インスタンス。
リグ、

3

ことに留意すべきである弱参照は、それらがもはや他の場所で参照されない場合、ガベージコレクタが追跡オブジェクトを処分することを可能にする他の指定されたソリューションと組み合わせて使用することができます。これにより、手動でオブジェクトを破棄したり、追跡されていることに気を付けたりするコードを必要とせずに、メモリリークが解消されます。ReferenceQueueを提供して、解放されたオブジェクトへの参照の通知を受け取ることができます。

静的配列または静的コレクションについて考えました。コンストラクターを介して、作成されたすべての新しいオブジェクトが追加されます。ただし、コンストラクターは継承されないため、これはサブクラスでは機能しません。

基本クラスのコンストラクターは、派生クラスのコンストラクターの前に呼び出されます。すべてのクラスには少なくとも1つのコンストラクターがあり、コンストラクターをオーバーライドできません。


2

ゲームを作成するとき、人々は時々、ゲームオブジェクトの各タイプの「自己管理」コレクションを必要とします。

1つの実装は次のようになります。

public class Car {

    static ArrayList<Car> list = new ArrayList<Car>();

    public Car() {
        list.add(this);
    }

    void kill() {
        list.remove(this);
    }

    static public void updateAll()
    {
        for (int i = list.size() - 1; i >= 0; i--)
        {
                list.get(i).update();
        }
    }

    public void update()
    {
        //update logic
    }
}

このようにして、コレクションを操作するメソッドを静的に宣言できる一方で、非静的メソッドはインスタンスを操作します(updateAllとupdate)。

非常に単純なシナリオでは問題ありませんが、中程度の複雑さでも、通常は個別のマネージャークラスを作成するのが最善です。


1
static ArrayList<ListeStatic> list = new ArrayList<ListeStatic>();ans supress statc {..} を直接記述できます
cl-r

2
Javaではメソッドの名前は小文字で始まりますuptdateAll(){..;}
CL-R

おっと...私はJavaを公共の場で放映してからしばらく経ちました
ケリートーマス

@KellyThomas車をリストに追加し、リストから削除します。不自然に聞こえます。
TulainsCórdova2013

1
@CayetanoGonçalvesは静的フィールドとして、すべてのインスタンスで共有される1つのリストです。
ケリートーマス

2

コンテキストを考えてみてください。オブジェクトを作成するときは、特定のコンテキストで作成します。たとえば、ゲームがエイリアンを撮影することである場合、アプリは常に新しいエイリアンオブジェクトを作成します。それらはSpace(メインUIを表すクラスの場合もあります)というフィールドに表示されます。

SpaceがcurrentAliensという名前のプロパティを持つことは完全に自然です。これは、作成する新しいエイリアンを追加する配列になります。ユーザーが時空の構造を引き裂いてすべてのエイリアンを一度に破壊できるようにしたい場合は、そのコレクションを反復処理して各オブジェクトを破壊します。

アプリの他の部分からこのエイリアンのコレクションにアクセスしたい場合(たとえば、設定ページから、ユーザーが特定の種類のエイリアンを一気に一掃できるようにする場合)、設定コンテキストはSpaceオブジェクトへのアクセス権を付与する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.