Verfolgen Sie alle Objekte einer Klasse

9

Ich bin neu in der objektorientierten Programmierung und stoße immer wieder auf dieses Problem. (Ich programmiere in Java) Ich habe ein bisschen gezögert, danach zu fragen, da es so ein grundlegendes Problem zu sein scheint, aber ich kann hier keine Informationen dazu oder Fragen dazu finden und keine davon Lehrbücher, die ich gelesen habe (natürlich auf einer ziemlich einfachen Ebene), haben dieses Thema angesprochen:

Oft muss ich alle Objekte einer Klasse verfolgen, die erstellt wurden, um sie für verschiedene Zwecke zu durchlaufen. So wie ich derzeit Programme schreibe, werden viele Objekte nur von anderen Objekten referenziert, was bedeutet, dass ich kein Array oder keine Sammlung habe, mit der ich sie alle referenzieren kann.

Ich stelle mir vor, dass es, da dies in OOP eine so grundlegende Notwendigkeit zu sein scheint, einen recht institutionalisierten und einfachen Weg geben sollte, dies zu tun? Ist es üblich, eine separate Liste aller Objekte einer Klasse zu führen?

Ich dachte an ein statisches Array oder eine statische Sammlung, zu der durch ihren Konstruktor jedes neu erstellte Objekt hinzugefügt wird. Dies würde jedoch nicht mit Unterklassen funktionieren, da Konstruktoren nicht vererbt werden?

Mir ist klar, dass diese Frage möglicherweise keine einfache Antwort hat. Ich hoffe nur, dass mich jemand ein bisschen über dieses Thema aufklären kann. Ich habe das Gefühl, dass mir hier ein zentrales Wissen fehlt.

zxz
quelle
5
Ein spezifischeres Beispiel für den verfolgten und den verfolgten Tracker könnte helfen. Dieses Problem wird je nach Kontext, Verwendungszweck usw. auf viele verschiedene Arten behandelt.
JustinC
2
Ich denke, Sie nähern sich dem Problem möglicherweise vom falschen Ende. Es ist nicht sehr üblich, eine Liste aller Instanzen einer bestimmten Klasse zu benötigen, und eine solche würde alle möglichen Entwurfsprobleme verursachen (da jetzt sogar Instanzen, die in völlig unabhängigen Kontexten erstellt wurden, durch diese Liste voneinander abhängen).
tdammers
1
"Durchlaufen Sie sie für verschiedene Zwecke" ... wie ...? Im Allgemeinen hat ein Objekt einen "Eigentümer" (kein formaler Begriff, sondern nur eine Aussage über die Programmsemantik), und es ist für niemanden anders, "verschiedene Zwecke" mit dem Objekt zu haben.
AakashM

Antworten:

8

Ich weiß nicht, warum Sie eine Liste aller Instanzen einer Klasse führen müssen.

Dies würde zu einem Speicherverlust führen, da diese Objekte niemals entsorgt werden, da die Liste sie weiterhin referenziert, nachdem dies keine andere Klasse getan hat.

Aber wenn Sie diesem Weg wirklich folgen wollen:

  1. Verwenden Sie das Factory-Muster. Eine Factory-Klasse mit Methoden, die die Klasse instanziieren und die Objekte zurückgeben. Auf diese Weise haben Sie einen zentralen Punkt, um die Instanziierungen zu steuern.
  2. Verwenden Sie das Singleton-Muster, um eine Liste oder Listen mit den Instanzen zu speichern.
  3. Lassen Sie die Fabrik jedes Objekt eines bestimmten Typs nach dem Erstellen in eine Liste aufnehmen.

Übrigens: Konstruktoren werden vererbt.

Tulains Córdova
quelle
Sie können der Factory natürlich eine "dispose" -Methode geben, mit der die Instanz aus der Liste der verfolgten Instanzen entfernt wird. Es gibt jedoch keine Möglichkeit, dies explizit aufzurufen. Oder geben Sie der Instanz eine Dispose-Methode, die die Dispose-Methode in ihrer Factory auslöst. Diese hat den gleichen Nachteil, wird jedoch mit etwas höherer Wahrscheinlichkeit tatsächlich aufgerufen, da sie näher am Benutzer liegt und besser sichtbar ist.
Jwenting
@jwenting Natürlich ist das ein Weg. Aber das würde hässliche, unnötige Abhängigkeiten zwischen den Klassen und der Fabrik schaffen. Klassen sollten nichts über die Fabrik wissen, die sie erstellt.
Tulains Córdova
Daher muss die Fabrik verfolgen, was sie erstellt, und nicht das Objekt, das die Fabrik
auffordert,
Ein Singleton würde technisch gesehen alle Instanzen enthalten, denke ich. Die eine einzige Instanz.
Rig
3

Es ist zu beachten, dass schwache Referenzen in Kombination mit den anderen angegebenen Lösungen verwendet werden können, damit der Garbage Collector verfolgte Objekte entsorgen kann, wenn sie nicht mehr an anderer Stelle referenziert werden. Dadurch werden Speicherverluste vermieden, ohne dass Code an anderer Stelle benötigt wird, um Objekte manuell zu entsorgen, oder auf andere Weise darauf zu achten, dass sie verfolgt werden. Sie können eine ReferenceQueue bereitstellen, um Benachrichtigungen über Verweise auf freigegebene Objekte zu erhalten.

Ich dachte an ein statisches Array oder eine statische Sammlung, zu der durch ihren Konstruktor jedes neu erstellte Objekt hinzugefügt wird. Dies würde jedoch nicht mit Unterklassen funktionieren, da Konstruktoren nicht vererbt werden?

Die Konstruktoren von Basisklassen werden vor Konstruktoren abgeleiteter Klassen aufgerufen. Jede Klasse hat mindestens einen Konstruktor und Konstruktoren können nicht überschrieben werden.

user2313838
quelle
2

Wenn Leute Spiele machen, wollen sie manchmal eine "selbstverwaltende" Sammlung jeder Art von Spielobjekt.

Eine Implementierung sieht folgendermaßen aus:

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
    }
}

Auf diese Weise können Methoden, die die Sammlung bearbeiten, als statisch deklariert werden, während nicht statische Methoden eine Instanz bearbeiten (updateAll vs. update).

Während dies für sehr einfache Szenarien in Ordnung ist , ist es bei mittlerer Komplexität normalerweise am besten, separate Managerklassen zu erstellen.

Kelly Thomas
quelle
1
Sie können direkt schreiben static ArrayList<ListeStatic> list = new ArrayList<ListeStatic>();und die Statistik unterdrücken {..}
cl-r
2
In Java beginnt der Name der Methode mit einem Kleinbuchstaben:uptdateAll(){..;}
cl-r
oops ... es ist schon eine Weile her, dass ich mein Java öffentlich ausgestrahlt habe
Kelly Thomas
@KellyThomas Ein Auto, das sich einer Liste hinzufügt und sich selbst daraus entfernt. Klingt unnatürlich.
Tulains Córdova
1
@ CayetanoGonçalves als statisches Feld ist eine Liste, die von allen Instanzen gemeinsam genutzt wird.
Kelly Thomas
2

Versuchen Sie, den Kontext zu denken. Wenn Sie ein Objekt erstellen, tun Sie dies in einem bestimmten Kontext. Wenn es in Ihrem Spiel beispielsweise darum geht, Aliens zu schießen, erstellt Ihre App ständig neue Alien-Objekte. Sie werden in einem Feld namens Space angezeigt (dies könnte die Klasse sein, die die Hauptbenutzeroberfläche darstellt).

Es ist für Space völlig selbstverständlich, eine Eigenschaft namens currentAliens zu haben, bei der es sich um ein Array handelt, zu dem Sie jedes neue Alien hinzufügen, das Sie erstellen. Wenn Sie Ihrem Benutzer erlauben möchten, die Struktur der Raumzeit auseinander zu reißen und alle Aliens gleichzeitig zu zerstören, würden Sie diese Sammlung durchlaufen und jedes Objekt zerstören.

Wenn Sie von anderen Teilen Ihrer App aus auf diese Sammlung von Aliens zugreifen möchten (z. B. von einer Einstellungsseite aus, auf der Benutzer möglicherweise bestimmte Arten von Aliens auf einen Schlag auslöschen möchten), wird Ihr Einstellungskontext angezeigt müssen Zugriff auf das Space-Objekt erhalten.

Wytze
quelle