web-dev-qa-db-ja.com

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

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

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

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

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

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

9
zxz

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

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

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

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

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

8

weak references を他の特定のソリューションと組み合わせて使用​​して、ガベージコレクターが追跡されたオブジェクトを他の場所で参照されなくなったときに破棄できるようにすることができます。これにより、オブジェクトを手動で破棄したり、追跡されていることに気を付けたりするコードを他の場所に必要とせずに、メモリリークが解消されます。 ReferenceQueueを提供して、解放されたオブジェクトへの参照の通知を受け取ることができます。

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

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

3
user2313838

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

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)。

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

2
Kelly Thomas

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

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

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

2
Wytze