Monitorando todos os objetos de uma classe

9

Eu sou novo na programação orientada a objetos e continuo com esse problema. (Estou programando em Java) Fiquei um pouco relutante em perguntar sobre isso, pois parece um problema tão básico, mas não consigo encontrar nenhuma informação sobre ele ou perguntas sobre isso aqui, e nenhuma das os livros que li (em um nível bastante básico) abordaram esse assunto:

Frequentemente, preciso acompanhar todos os objetos de uma classe que foram criados, para percorrer os mesmos para vários propósitos. Da maneira como atualmente escrevo programas, muitos objetos são referenciados apenas de outros objetos, o que significa que não tenho matriz ou coleção com a qual referenciar todos eles.

Eu imagino que, como isso parece uma necessidade muito básica na OOP, deve haver uma maneira bastante institucionalizada e simples de fazer isso? É prática comum manter uma lista separada de todos os objetos de uma classe?

Pensei em uma matriz ou coleção estática, à qual, através de seu construtor, todos os novos objetos criados seriam adicionados. No entanto, isso não funcionaria com subclasses, uma vez que os construtores não são herdados?

Sei que essa pergunta pode não ter uma resposta fácil; Eu só espero que alguém possa me esclarecer um pouco sobre esse assunto. Sinto como se estivesse sem um conhecimento central aqui.

zxz
fonte
5
Um exemplo mais específico do rastreado e do rastreador pode ajudar. Esse problema é tratado de várias maneiras diferentes, dependendo do contexto, como elas são usadas e assim por diante.
JustinC
2
Eu acho que você pode estar abordando o problema do lado errado. Não é muito comum precisar de uma lista de todas as instâncias de uma determinada classe, e ter uma causaria todos os tipos de problemas de design (porque agora mesmo as instâncias criadas em contextos totalmente independentes dependem uma da outra nessa lista).
tdammers
11
"iterar através deles para vários propósitos" ... como ...? Geralmente, um objeto tem um 'proprietário' (não um termo formal, mais apenas uma declaração sobre a semântica do programa), e não é para ninguém ter 'vários propósitos' com o objeto.
AakashM

Respostas:

8

Não sei por que você precisa manter uma lista de todas as instâncias de uma classe.

Isso causaria vazamento de memória, pois esses objetos nunca serão descartados, uma vez que a lista ainda os fará referência depois que nenhuma outra classe o fizer.

Mas se você realmente deseja seguir esse caminho:

  1. Use o padrão de fábrica. Uma classe de fábrica com métodos que instanciam a classe e retornam os objetos. Dessa forma, você tem um ponto centralizado para controlar as instanciações.
  2. Use o padrão Singleton para armazenar uma lista ou listas que contêm as instâncias.
  3. Faça a fábrica colocar cada objeto de um determinado tipo em uma lista depois de criá-los.

A propósito: construtores são herdados.

Tulains Córdova
fonte
É claro que você pode fornecer à fábrica um método de "descarte" que remove a instância de sua lista de instâncias rastreadas. Mas não há como explicitamente invocá-lo. Ou forneça à instância um método de descarte que aciona o método de descarte em sua fábrica, que tem a mesma desvantagem, mas é um pouco mais provável de ser chamado de fato, pois é mais próximo do usuário, mais visível.
jwenting
@jwenting Claro que é uma maneira. Mas isso criaria dependências feias e desnecessárias entre as classes e a fábrica. As aulas não devem saber nada sobre a fábrica que as cria.
Tulains Córdova
portanto, ter a faixa de manter fábrica do que ele cria, em vez do objeto dizendo a fábrica para registrá-lo ...
jwenting
Um singleton tecnicamente conteria todas as instâncias, eu acho. A única instância.
Rig
3

Deve-se notar que referências fracas podem ser usadas em combinação com as outras soluções fornecidas para permitir que o coletor de lixo descarte os objetos rastreados quando eles não forem mais referenciados em outro lugar. Isso elimina vazamentos de memória sem exigir código em outro lugar para descartar manualmente os objetos ou cuidar de que eles estejam sendo rastreados. Você pode fornecer um ReferenceQueue para receber uma notificação de referências a objetos que foram liberados.

Pensei em uma matriz ou coleção estática, à qual, através de seu construtor, todos os novos objetos criados seriam adicionados. No entanto, isso não funcionaria com subclasses, uma vez que os construtores não são herdados?

Os construtores das classes base são chamados antes dos construtores das classes derivadas. Toda classe tem pelo menos um construtor e os construtores não podem ser substituídos.

user2313838
fonte
2

Ao criar jogos, as pessoas às vezes desejam uma coleção "autogerenciada" de cada tipo de objeto do jogo.

Uma implementação é assim:

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

Dessa maneira, os métodos de manipulação da coleção podem ser declarados estáticos, enquanto os métodos não estáticos manipulam uma instância (updateAll vs. update).

Embora adequado para cenários muito simples, mesmo com complexidade moderada, geralmente é melhor criar classes de gerente separadas.

Kelly Thomas
fonte
11
Você pode escrever diretamente static ArrayList<ListeStatic> list = new ArrayList<ListeStatic>();e suprimir o statc {..}
cl-r
2
Em Java, o nome do método começa com uma letra minúscula:uptdateAll(){..;}
cl-r
oops ... tem sido um tempo desde que eu transmitida meu java em público
Kelly Thomas
@KellyThomas Um carro se adicionando a uma lista, eles se retirando dele. Parece antinatural.
Tulains Córdova
11
@ CayetanoGonçalves como campo estático, é uma lista compartilhada por todas as instâncias.
9788 Kelly Key Thomas
2

Tente pensar no contexto. Quando você cria um objeto, você o faz em um determinado contexto. Por exemplo, se seu jogo é sobre atirar em alienígenas, seu aplicativo cria novos objetos alienígenas o tempo todo. Eles serão exibidos em um campo chamado Space (que pode ser a classe que representa a interface do usuário principal).

É perfeitamente natural que o Space tenha uma propriedade chamada currentAliens, que seria uma matriz, à qual você adiciona cada novo alienígena que criar. Se você deseja permitir que seu usuário rasgue o tecido do espaço-tempo e destrua todos os alienígenas de uma só vez, você percorrerá essa coleção e destruirá cada objeto.

Se você quiser ter acesso a essa coleção de alienígenas de outras partes do seu aplicativo (por exemplo, em uma página Configurações, onde você pode permitir que os usuários destruam certos tipos de alienígenas de uma só vez), o contexto Configurações será precisa ter acesso ao objeto Space.

Wytze
fonte