При каждом изменении isValid всем прямым потомкам увеличиваем invalidParents на 1
А как мы это делаем? Если рекурсивно (сначала детям, потом детям детей и т.д.), то что делать, если у двух детей общий внук (он увеличится два раза). Придётся сначала составить список всех потомков без повторений. Или мы только детям увеличиваем?
Вот еще раз мой код, но теперь с комментариями:
public void update(boolean fromParent) { // этот метод вызывается из родителя и сообщает, что родитель стал невалидным
if (isValid) { // если текущий объект был валидным, то:
isValid = false; // делаем его невалидным и потом
for (int i = 0; i < children.size(); i++) {
children.get(i).update(true); // оповещаем каждого потомка, что у него один родитель стал невалидным
}
}
// счетчик невалидных родителей увеличиваем на единицу
if (fromParent) {
invalidParents++;
}
}
В сумме это работает так: каждый родитель вызывает метод
update у потомка; потомок становится невалидным и передает информацию дальше по цепочке. Оповещение потомков срабатывает только при первом вызове от родителя (пока у самого объекта
isValid = true), а
invalidParents++; срабатывает каждый раз - чтобы корректно посчитать количество невалидных родителей. В первоначальной версии у меня была ошибка, о которой вы говорите, на нее же указывал
mihaild, а это - исправленная версия.
Кстати, интересный вариант задачи: если объект уничтожается (фигура удаляется), он шлёт сигнал "умер" (destroyed). Его дети от этого сигнала тоже умирают и шлют сигнал destroyed и т.д. Рисовальная машинка на каждый сигнал перерисовывает картинку (правда, пересчитывать ничего не надо, просто его не рисовать). Как подождать, пока они все умрут? Тут особенность в том, что умерший объект уже никаких сигналов воспринимать не будет и никакой учёт вести не может.
Мммм... Я сначала написал длинный ответ, а потом удалил. Удаление дочернего объекта должно случиться, только если у него "умерли" все родители, правильно? Тогда алгоритм усложняется, надо подумать. Кажется, тогда стоит вместо логической переменной
isValid сделать статус с тремя возможными значениями (
Valid,
Invalid,
Dead), обновлять всех потомков (и у каждого считать количество мертвых и невалидных родителей отдельно), потом сначала все объекты, у которых все родители мертвые, удалить, а потом пересчитать невалидные объекты.
В любом случае, как мне кажется, асинхронные сигналы тут не очень удобны (как я понял из объяснений
Dmitriy40, они асинхронные), потому что вам мало отправить сигнал, вам нужна гарантия, что он получен и обработан. Поэтому я предлагаю вместо сигналов делать прямые вызовы методов потомков. Как только метод завершился, вы точно знаете, что все обработано.
Хотя возможно я просто не привык к работе с сигналами.