Ассоциация, агрегация и композиция в Java - Вопросы
Всего: 5 вопросов
1. Чем агрегация отличается от композиции?
Чем агрегация отличается от композиции?
Оба отношения описывают связь «часть—целое», но различаются силой связи и жизненным циклом части. При агрегации часть создаётся внешним кодом и передаётся целому (в конструктор или сеттер), может принадлежать нескольким целым и продолжает существовать после исчезновения целого: new PC(keyboard), отдел и сотрудники. При композиции часть создаёт само целое внутри своего конструктора, часть принадлежит только ему и умирает вместе с ним: this.keyboard = new Keyboard(), дом и комнаты. В UML агрегация — незакрашенный (белый) ромб у целого, композиция — закрашенный (чёрный).
2. Что такое отношения IS-A и HAS-A между классами в Java?
Что такое отношения IS-A и HAS-A между классами в Java?
IS-A («является») основано на наследовании классов или реализации интерфейсов: class Lorry extends Car означает Lorry IS-A Car, а class Transport implements Moveable — Transport IS-A Moveable. Проверить IS-A в коде можно оператором instanceof. HAS-A («имеет») основано на использовании: один класс хранит ссылку на объект другого класса в поле — class Car { Engine engine; } означает Car HAS-A Engine. Ассоциация, агрегация и композиция — это уточнения HAS-A.
3. Что такое ассоциация и какие у неё бывают направленность и кратность?
Что такое ассоциация и какие у неё бывают направленность и кратность?
Ассоциация — зонтичный термин для связи, при которой объекты двух классов могут ссылаться друг на друга: class Person { private Car car; }. Агрегация и композиция — её частные случаи. По направленности ассоциация бывает односторонней (о другом классе знает только один) и двусторонней (оба хранят ссылки друг на друга). По кратности — один к одному (человек и его автомобиль), один ко многим (магазин и категории), многие ко многим (студенты и курсы); сторона «ко многим» выражается коллекцией или массивом. Двустороннюю связь нужно обновлять одним методом сразу с обеих сторон, иначе данные рассогласуются, а в toString() или equals() может возникнуть бесконечная рекурсия.
4. Почему в проектировании предпочитают композицию наследованию (composition over inheritance)?
Почему в проектировании предпочитают композицию наследованию (composition over inheritance)?
Правило сформулировано в книге «Приёмы объектно-ориентированного проектирования» (банда четырёх) и повторено Джошуа Блохом в Effective Java. Избыточное наследование делает код хрупким (изменение базового класса ломает наследников), нарушает инкапсуляцию (подкласс зависит от деталей реализации родителя), даёт жёсткую иерархию, зафиксированную на этапе компиляции, и упирается в запрет множественного наследования. Композиция гибче: вместо class Driver extends Employee лучше дать сотруднику поле private Role role — роль можно сменить в любой момент через сеттер. Наследование оправдано, только если подкласс является полноценной заменой родителя (принцип подстановки Лисков) и вы контролируете оба класса.
5. Что такое зависимость (dependency) и как виды связей выстраиваются по силе?
Что такое зависимость (dependency) и как виды связей выстраиваются по силе?
Зависимость — самая слабая связь: класс не хранит объект в поле, а получает его как параметр метода, создаёт локально или возвращает из метода, поэтому связь живёт только на время вызова. Пример: void print(Printer printer) в классе ReportService без поля типа Printer. По возрастанию силы связи отношения выстраиваются так: зависимость → ассоциация → агрегация → композиция → наследование. Чем связь сильнее, тем труднее менять классы независимо друг от друга, поэтому в проектировании стремятся к слабой связанности.