Realizar un seguimiento de todos los objetos de una clase

9

Soy nuevo en la programación orientada a objetos y sigo encontrando este problema. (Estoy programando en Java) He sido un poco reacio a preguntar sobre esto, ya que parece ser un problema tan básico, pero no puedo encontrar ninguna información al respecto, o preguntas al respecto aquí, y ninguno de los Los libros de texto que he leído (en un nivel bastante básico, por supuesto) han tocado este tema:

A menudo necesito hacer un seguimiento de todos los objetos de una clase que se han creado, para iterar a través de ellos para diversos fines. En la forma en que actualmente escribo programas, muchos objetos solo están referenciados desde otros objetos, lo que significa que no tengo una matriz o colección con la que hacer referencia a todos.

Me imagino que, como esto parece una necesidad tan básica en OOP, ¿debería haber una manera bastante institucionalizada y simple de hacerlo? ¿Es una práctica habitual mantener una lista separada de todos los objetos de una clase?

Pensé en una matriz o colección estática, a la que a través de su constructor, se agregaría cada nuevo objeto creado. Sin embargo, esto no funcionaría con subclases, ya que los constructores no se heredan.

Me doy cuenta de que esta pregunta podría no tener una respuesta fácil; Solo espero que alguien pueda aclararme un poco sobre este tema. Siento que si me falta un conocimiento central aquí.

zxz
fuente
55
Un ejemplo más específico de seguimiento y seguimiento podría ayudar. Este problema se maneja de muchas maneras diferentes según el contexto, cómo se usan, etc.
JustinC
2
Creo que podrías estar abordando el problema desde el extremo equivocado. No es muy común necesitar una lista de todas las instancias de una clase determinada, y tener una causaría todo tipo de problemas de diseño (porque ahora incluso las instancias creadas en contextos totalmente no relacionados dependen entre sí a través de esta lista).
tdammers
1
"iterar a través de ellos para diversos fines" ... como ...? En general, un objeto tiene un 'propietario' (no es un término formal, sino más bien una declaración sobre la semántica del programa), y no le corresponde a nadie tener 'varios propósitos' con el objeto.
AakashM

Respuestas:

8

No sé por qué necesitas mantener una lista de todas las instancias de una clase.

Eso causaría una pérdida de memoria ya que esos objetos nunca se eliminarán, ya que la lista seguirá haciendo referencia a ellos después de que ninguna otra clase lo haga.

Pero si realmente quieres seguir esa ruta:

  1. Usa el patrón Factory. Una clase de fábrica con métodos que instancian la clase y devuelven los objetos. De esa manera, tiene un punto centralizado para controlar las instancias.
  2. Use el patrón Singleton para mantener una lista o listas que contienen las instancias.
  3. Haga que la fábrica ponga cada objeto de cierto tipo en una lista después de crearlos.

Por cierto: los constructores son heredados.

Tulains Córdova
fuente
Por supuesto, puede darle a la fábrica un método de "eliminación" que elimine la instancia de su lista de instancias rastreadas. Pero no hay forma de invocarlo explícitamente. O proporcione a la instancia un método de eliminación que active el método de eliminación en su fábrica, que tiene el mismo inconveniente, pero es más probable que se llame a medida que está más cerca del usuario, más visible.
Jwenting
@jwenting Por supuesto que es una manera. Pero eso crearía dependencias feas e innecesarias entre las clases y la fábrica. Las clases no deben saber nada sobre la fábrica que las crea.
Tulains Córdova
por lo tanto, tener el no perder la fábrica de lo que crea, en lugar del objeto contando la fábrica para registrarlo ...
jwenting
Un singleton técnicamente tendría todas las instancias, supongo. La única instancia.
Aparejo
3

Cabe señalar que se pueden usar referencias débiles en combinación con las otras soluciones dadas para permitir que el recolector de basura elimine los objetos rastreados cuando ya no se hace referencia a ellos en otro lugar. Esto elimina las pérdidas de memoria sin requerir código en otro lugar para deshacerse manualmente de los objetos, o de lo contrario cuidar que se estén rastreando. Puede proporcionar un ReferenceQueue para recibir notificaciones de referencias a objetos que se han liberado.

Pensé en una matriz o colección estática, a la que a través de su constructor, se agregaría cada nuevo objeto creado. Sin embargo, esto no funcionaría con subclases, ya que los constructores no se heredan.

Los constructores de clases base se invocan antes que los constructores de clases derivadas. Cada clase tiene al menos un constructor y los constructores no pueden ser anulados.

usuario2313838
fuente
2

Al hacer juegos, las personas a veces quieren una colección "autogestionada" de cada tipo de objeto de juego.

Una implementación se ve así:

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

De esta manera, los métodos que manipulan la colección pueden declararse estáticos, mientras que los métodos no estáticos manipulan una instancia (updateAll vs. update).

Si bien está bien para escenarios muy simples, incluso con una complejidad moderada, generalmente es mejor crear clases de administrador separadas.

Kelly Thomas
fuente
1
Puede escribir directamente static ArrayList<ListeStatic> list = new ArrayList<ListeStatic>();y suprimir el statc {..}
cl-r
2
En Java, el nombre del método comienza con una letra minúscula:uptdateAll(){..;}
cl-r
oops ... ha pasado un tiempo desde que transmití mi Java en público
Kelly Thomas
@KellyThomas Un auto que se agrega a una lista, y que se quitan de él. Suena antinatural.
Tulains Córdova
1
@ CayetanoGonçalves como campo estático es una lista compartida por todas las instancias.
Kelly Thomas
2

Intenta pensar en el contexto. Cuando crea un objeto, lo hace en un determinado contexto. Por ejemplo, si su juego consiste en disparar alienígenas, su aplicación creará nuevos objetos alienígenas todo el tiempo. Se mostrarán en un campo llamado Espacio (que podría ser la clase que representa la IU principal).

Es perfectamente natural que Space tenga una propiedad llamada currentAliens, que sería una matriz, a la que agrega cada nuevo alienígena que cree. Si desea permitir que su usuario desgarre la estructura del espacio-tiempo y destruya a todos los extraterrestres a la vez, debe recorrer esa colección y destruir cada objeto.

Si desea tener acceso a esta colección de extraterrestres desde otras partes de su aplicación (por ejemplo, desde una página de Configuración, donde puede permitir que los usuarios eliminen ciertos tipos de extraterrestres de una sola vez), su contexto de Configuración necesitan tener acceso al objeto Space.

Wytze
fuente