Відстеження всіх об'єктів класу


9

Я новачок в об'єктно-орієнтованому програмуванні і продовжую працювати з цим питанням. (Я програмую на Java) Я трохи не хотів питати про це, оскільки це здається такою основною проблемою, але я не можу знайти тут жодної інформації, або питань щодо неї, і жодного з підручники, які я прочитав (на досить базовому рівні курсу), торкнувся цього питання:

Часто мені потрібно відслідковувати всі створені об’єкти класу, переглядати їх для різних цілей. Таким чином, я зараз пишу програми, на багато об'єктів посилаються лише інші об'єкти, тобто я не маю масиву чи колекції, з якою б посилатися на них усіх.

Я гадаю, що, як це здається такою дуже основною потребою в ООП, для цього повинен бути досить інституціоналізований і простий спосіб? Чи звичайна практика зберігати окремий список усіх об’єктів класу?

Я подумав про статичний масив або колекцію, до якої через його конструктор буде доданий кожен створений новий об’єкт. Однак це не буде працювати з підкласами, оскільки конструктори не успадковуються?

Я усвідомлюю, що це запитання може не мати простої відповіді; Я просто сподіваюся, що хтось може трохи просвітити мене з цього приводу. Я відчуваю себе, якби мені бракує центральної частини знань.


5
Більш конкретний приклад відстеженого та трекера може допомогти. Ця проблема вирішується багатьма різними способами залежно від контексту, способу їх використання тощо.
JustinC

2
Я думаю, що ти можеш підійти до проблеми з неправильного кінця. Не дуже часто потрібен перелік усіх примірників даного класу, а наявність одного може спричинити всілякі проблеми з дизайном (адже зараз навіть екземпляри, створені у абсолютно не пов'язаних контекстах, залежать один від одного через цей список).
tdammers

1
"повторити їх для різних цілей" ... таких як ...? Як правило, об’єкт має одного "власника" (не формальний термін, а просто висловлювання про семантику програми), і це не має для кого-небудь іншого "різних цілей" з об'єктом.
AakashM

Відповіді:


8

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

Це може спричинити витік пам'яті, оскільки ці об’єкти ніколи не будуть утилізовані, оскільки список все ще посилатиметься на них після того, як це не зробить жоден інший клас.

Але якщо ви дійсно хочете йти цим маршрутом:

  1. Використовуйте заводський візерунок. Фабричний клас із методами, які інстанціюють клас та повертають об'єкти. Таким чином у вас є централізована точка для контролю над моментами.
  2. Використовуйте шаблон Singleton, щоб утримувати список або списки, що містять екземпляри.
  3. Зробіть так, щоб завод створював кожен об’єкт певного типу у списку після їх створення.

До речі: конструктори передаються у спадок.


Звичайно, ви можете надати фабриці метод "розпорядження", який видаляє екземпляр зі списку відстежуваних екземплярів. Але явно не можна посилатися на це. Або надайте екземпляру метод розпорядження, який запускає метод вибуття на його заводі, який має той самий недолік, але трохи більше шансів, що він буде фактично викликаний, оскільки він ближче до користувача, більш помітний.
1313

@jwenting Звичайно, це спосіб. Але це створило б потворні, непотрібні залежності між класами та фабрикою. Класи не повинні нічого знати про фабрику, яка їх створює.
Tulains Córdova

отже, фабрика слідкує за тим, що вона створює, а не об’єктом, який каже фабриці зареєструвати це ...
jwenting

Однотонний технічно тримав би всі екземпляри, напевно. Один єдиний екземпляр.
Ріг

3

Слід зазначити, що слабкі посилання можуть використовуватися в поєднанні з іншими даними рішеннями, що дозволяють сміттєзбиральнику утилізувати відслідковувані об'єкти, коли вони більше не посилаються в іншому місці. Це усуває витоки пам’яті, не вимагаючи коду в іншому місці для ручного розпорядження об’єктами або іншим чином піклуючись про їх відстеження. Ви можете надати ReferenceQueue, щоб отримувати повідомлення про посилання на звільнені об'єкти.

Я подумав про статичний масив або колекцію, до якої через його конструктор буде доданий кожен створений новий об’єкт. Однак це не буде працювати з підкласами, оскільки конструктори не успадковуються?

Конструктори базових класів викликаються перед конструкторами похідних класів. У кожному класі є щонайменше один конструктор, і конструктори не можуть бути відмінені.


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 vs. update).

Хоча добре для дуже простих сценаріїв, навіть при помірній складності, як правило, найкраще створювати окремі класи менеджерів.


1
Ви можете безпосередньо написати static ArrayList<ListeStatic> list = new ArrayList<ListeStatic>();ans supress statc {..}
cl-r

2
Ім'я методу Java починається з малої літери:uptdateAll(){..;}
cl-r

ой, минув час, коли я публічно видавав свою публічну публіку
Келлі Томас,

@KellyThomas Автомобіль, який додає себе до списку, видаляє його з нього. Звучить неприродно.
Tulains Córdova

1
@ CayetanoGonçalves як статичне поле - це один список, яким поділяються всі екземпляри.
Келлі Томас

2

Спробуйте продумати контекст. Створюючи об’єкт, ви робите це в певному контексті. Наприклад, якщо у вашій грі йдеться про зйомку прибульців, ваш додаток буде постійно створювати нові чужі об’єкти. Вони будуть відображатися в полі під назвою Space (яке може бути класом, який представляє основний інтерфейс користувача).

Цілком природно для Space мати властивість з назвою currentAliens, яка була б масивом, до якого ви додаєте кожного нового створеного вами іноземця. Якщо ви хочете дозволити своєму користувачеві розірвати тканину простору та знищити всіх прибульців одразу, ви переглянете цю колекцію та знищите кожен об’єкт.

Якщо ви хочете отримати доступ до цієї колекції прибульців з інших частин програми (скажімо, на сторінці налаштувань, де ви можете дозволити користувачам видаляти певні типи прибульця одним махом), ваш контекст налаштувань буде потрібно отримати доступ до космічного об’єкта.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.