
Наследование - создание нового объекта на основе существующего. Это статическое связывание, определяется на стадии компиляции. Используется термин «является». Например, дельфин является млекопитающим. Наследование – высокая связанность. Объекты невозможно разделить в процессе выполнения программы.
Для композиции и агрегации можно использовать термин «содержит». Вот только содержат они по-разному.
Композиция – «состоит из». Например, огурец содержит семена (состоит, в том числе, и из них). Семена не существуют без огурца и завершают своё существование вместе с его «гибелью». Если выражаться языком кода, то объект «Огурец» содержит в себе приватное поле – массив или коллекцию - типа «Семечко», которое будет заполняться, например, в конструкторе. Т.е. объекты типа «Семечко» создаются прямо внутри класса «Огурец».
class Seed {}
class Cucumber {
private List<Seed> seeds = new ArrayList<>();
Cucumber() {
for (int i = 0; i < 100500; i++) {
seeds.add(new Seed ());
}
}
}
Композиция – тесная связанность.Агрегация. Наиболее понятный термин для агрегации – «использует». Например, настольная лампа – освещает область рабочего стола. Для этого она использует лампочку, поскольку сама по себе она освещать не способна. Лампочки изготавливаются где-то отдельно, независимо от настольных ламп. Лампочка вворачивается в патрон настольной лампы. Т.о. настольная лампа использует лампочку.
class LEDBulb extends Bulb {}
class TableLamp {
private Bulb bulb;
TableLamp(Bulb someBulb) {
bulb = someBulb;
}
}
Передаём объект светодиодной лампочки в конструктор настольной лампы извне:
Bulb ledBulb = new LEDBulb();
TableLamp lamp = new TableLamp(ledBulb);
Жизненный цикл лампочки напрямую никак не зависит от жизненного цикла настольной лампы. Если мы отвяжем ссылку lamp от объекта настольной лампы, то объект светодиодной лампочки всё равно продолжит существовать.
lamp = null; // объект TableLamp стал доступен для сборщика мусора.
// но ledBulb продолжает ссылаться на объект LEDBulb
Агрегация – слабое связывание.