Правильно ли я понимаю отношение классов "Композиция" в ООП?
Изучаю тему Композиция в ООП. Пересмотрел много видео и прочитал много разных статей. Термины для единого контекста: Главный объект - это объект в свойствах которого есть ссылки на другие объекты (составные части). Составная часть - это объект, который не может существовать сам по себе и всегда является частью другого объекта, в нашем случае Главного объекта. Пример: Тело человека - это главный объект, а рука, сердце, печень и др. органы - это составные части, которые сами по себе не могут существовать.
Далее из этого следует, что Композиция позволяет управлять временим жизни составной частью объекта, т.е. при удалении Главного объекта, должны удалится все его составные части, потому что составная часть не может существовать без основного объекта. Верно?
Если это утверждение верное, тогда рассуждаю дальше....В JAVA объекты удаляются автоматически, если на них нет ссылок. Допустим я удаляю единственную ссылку на Главный объект, значит gc должен удалить Главный объект и все его составные части. Но вдруг где то хранится ссылка составной части за пределами Главного объекта? Тогда gc не сможет удалить эту составную часть, т.е. Главный объект будет удален, а его составные части нет.
Мое мнение: Композиция - это когда ссылки на составные части хранится только в одном месте в Главном объекте. Далее, где бы мы не создали составную часть, в теле Главного объекта или за его пределами - ссылка на составную часть должна существовать в единственном экземпляре в свойствах Главного объекта.
Если объект (составная часть) создается внутри тела Главного объекта, значит должны отсутствовать геттеры, которые отдают ссылку на составную часть за пределы Главного объекта. Здесь можно реализовать геттер таким образом, что бы в теле метода создавалась копия составной части и возвращалась ссылка на копию.
Если объект (составная часть) создаётся за пределами Главного объекта и встраивается через параметр метода или конструктор или сеттер, тогда опять делается копия составной части и в новая ссылка хранится в свойствах основного объекта.
Для меня в композиции главное одно: ссылки на составные части объекта хранятся в единственном экземпляре в свойствах Главного объекта.
Поправьте меня если я не правильно понимаю композицию. Кто что думает по этому поводу?
"Да нет, доктор, со мной все нормально, просто слова такие интересные - эрекция! эякуляция!.." (с)
Практикой займитесь вместо высасывания из пальца натянутых аналогий - и все встанет на место.
И окажется, что необязательно сеттеры-геттеры, можно просто паблик, если надо.
И вместо теоретических "составных частей" окажется, что объект хранит в члене такую же ссылку, как и любой другой ссылающийся, так что сборщик разберется...
Возможно, станет скучнее. Но полезнее.
Главного объекта, должны удалится все его составные части, потому что составная часть не может существовать без основного объекта. Верно?
Нет такого утверждения в ООП и в реальном мире тоже нет. Взять ваш пример с человеком и органами - после смерти человека, его органы могут быть использованы для пересадки другим людям (если они здоровы и пересадка законна).
Спасибо за ответ! Я бы не стал опираться на пример с телом человека....это пример для наглядности.
В жизни сложно найти такой пример, а вот в программировании наверное много.
Допустим вы обрабатываете массив объектов. Вам нужно удалить по фильтру. Вы удаляете кучу объектов, а составные части остались жить своей жизнью, потому что другой программист воспользовался геттером и получил кучу составных частей (объектов) для своей работы. GC удалил главные объекты, а составные части продолжают жить.
Иначе я не понимаю зачем разделять отношение классов на агрегацию и композицию.
Денис, да, тут вы правы. Если внутренние объекты закрыты прайватами и не доступны никакими гетами (и важно, что объекты составного класса создаются внутри самостоятельно, а не передаются в конструкторе), то это Композиция, а если ссылку можно получить извне без рефлексии, то это Агрегация.
Чисто вопрос для джунов на собеседовании - практического смысла в разделении нет.
Дмитрий , спасибо за ответ!
Тут я осознал следующее, что Композиция - это жесткая инкапсуляция. По сути я не могу обратиться напрямую к составной части объекта и не могу получить ссылку на составную часть. Я могу взаимодействовать с составной частью только через public методы Главного объекта, если это реализовано.