Отслеживание всех объектов класса

9

Я новичок в объектно-ориентированном программировании и продолжаю сталкиваться с этой проблемой. (Я программирую на Java) Я немного неохотно спрашиваю об этом, поскольку это кажется такой основной проблемой, но я не могу найти какую-либо информацию по этому вопросу или вопросы по этому поводу здесь, и ни один из Учебники, которые я прочитал (на довольно базовом уровне, конечно), затронули эту проблему:

Часто мне нужно отслеживать все объекты класса, которые были созданы, чтобы перебирать их для различных целей. Они, как я сейчас пишу программы, на многие объекты ссылаются только из других объектов, то есть у меня нет массива или коллекции, с которой можно ссылаться на них все.

Я полагаю, что, поскольку в ООП это кажется такой фундаментальной необходимостью, должен быть достаточно институционализированный и простой способ добиться этого? Является ли обычной практикой ведение отдельного списка всех объектов класса?

Я думал о статическом массиве или коллекции, в которую через его конструктор будут добавляться все новые созданные объекты. Это однако не будет работать с подклассами, так как конструкторы не наследуются?

Я понимаю, что на этот вопрос может не быть простого ответа; Я просто надеюсь, что кто-то может немного просветить меня по этому вопросу. Я чувствую, что мне не хватает центральной части знаний здесь.

ZxZ
источник
5
Более конкретный пример отслеживаемого и трекера может помочь. Эта проблема решается разными способами в зависимости от контекста, способа их использования и т. Д.
JustinC
2
Я думаю, что вы, возможно, подходите к проблеме не с того конца. Не очень часто требуется список всех экземпляров данного класса, и наличие одного вызовет все виды проблем проектирования (потому что теперь даже экземпляры, созданные в совершенно не связанных контекстах, зависят друг от друга через этот список).
tdammers
1
"перебирать их для различных целей" ... например ...? Как правило, у объекта есть один «владелец» (не формальный термин, а просто утверждение о семантике программы), и никто не должен иметь «различные цели» с объектом.
AakashM

Ответы:

8

Я не знаю, почему вам нужно вести список всех экземпляров класса.

Это может привести к утечке памяти, поскольку эти объекты никогда не будут уничтожены, поскольку список будет по-прежнему ссылаться на них после того, как этого не сделает другой класс.

Но если вы действительно хотите следовать по этому пути:

  1. Используйте шаблон Factory. Фабричный класс с методами, которые создают экземпляр класса и возвращают объекты. Таким образом, у вас есть централизованная точка управления экземплярами.
  2. Используйте шаблон Singleton для хранения списка или списков, содержащих экземпляры.
  3. Сделайте так, чтобы фабрика помещала каждый объект определенного типа в список после их создания.

Кстати: конструкторы наследуются.

Тулаинс Кордова
источник
Конечно, вы можете дать фабрике метод «dispose», который удалит экземпляр из списка отслеживаемых экземпляров. Но нет никакого способа явно вызвать это. Или предоставьте экземпляру метод dispose, который запускает метод dispose на своей фабрике, который имеет тот же недостаток, но с меньшей вероятностью будет фактически вызван, так как он ближе к пользователю, более заметен.
празднуя
@jwenting Конечно, это способ. Но это создало бы уродливые, ненужные зависимости между классами и фабрикой. Классы не должны ничего знать о фабрике, которая их создает.
Тулаинс Кордова
следовательно, фабрика следит за тем, что она создает, а не объект, который
приказывает
Синглтон технически будет держать все экземпляры, я думаю. Единственный экземпляр.
Рог
3

Следует отметить, что слабые ссылки могут использоваться в сочетании с другими данными решениями, чтобы сборщик мусора мог избавиться от отслеживаемых объектов, когда на них больше нет ссылок в другом месте. Это устраняет утечки памяти, не требуя кода в другом месте для удаления объектов вручную или иным образом заботясь о том, чтобы они отслеживались. Вы можете предоставить ReferenceQueue для получения уведомления о ссылках на объекты, которые были освобождены.

Я думал о статическом массиве или коллекции, в которую через его конструктор будут добавляться все новые созданные объекты. Это однако не будет работать с подклассами, так как конструкторы не наследуются?

Конструкторы базовых классов вызываются перед конструкторами производных классов. Каждый класс имеет по крайней мере один конструктор, и конструкторы не могут быть переопределены.

user2313838
источник
2

При создании игр людям иногда требуется «самоуправляемая» коллекция игровых объектов каждого типа.

Одна реализация выглядит так:

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>();и подавить статистику {..}
cl-r
2
В Java имя метода начинается со строчной буквы:uptdateAll(){..;}
cl-r
упс ... прошло много времени с тех пор, как я транслировал свою публичную Java-версию
Келли Томас,
@KellyThomas Автомобиль, добавляющий себя в список, а сам удаляющий его из списка. Звучит неестественно.
Тулаинс Кордова
1
@ CayetanoGonçalves как статическое поле, это один список, общий для всех экземпляров.
Келли Томас
2

Попробуйте продумать контекст. Когда вы создаете объект, вы делаете это в определенном контексте. Например, если ваша игра о стрельбе по инопланетянам, ваше приложение будет постоянно создавать новые инопланетные объекты. Они будут отображаться в поле с именем Space (это может быть класс, представляющий основной пользовательский интерфейс).

Для Space вполне естественно иметь свойство currentAliens, которое будет массивом, к которому вы добавляете каждого нового созданного вами пришельца. Если вы хотите позволить своему пользователю разорвать ткань пространства-времени и уничтожить сразу всех инопланетян, вы должны пройти по этой коллекции и уничтожить каждый объект.

Если вы хотите иметь доступ к этой коллекции пришельцев из других частей вашего приложения (скажем, со страницы настроек, где вы можете разрешить пользователям уничтожать определенные типы пришельцев одним махом), контекст ваших настроек будет нужно предоставить доступ к космическому объекту.

Wytze
источник