X

Просто про наследование, композицию и агрегацию в PHP

К моему удивлению, очень часто возникает непонимание в чем же отличие между наследованием, композицией и агрегацией. Приведу, пару простых примеров, которые без лишней воды продемонстрируют отличия..

Что такое наследование, композиция и агрегация

Наследование, композиция и агрегация - это способы взаимодействия классов между собой. Т.е. как один класс может использовать методы другого класса.

Композиция и Агрегация является подвидом Ассоциации. Звучит, не понятно, но не все так сложно..

Очень сложно, до свидания

Для, того чтобы было более понятно, я организую всю эту структуру в такой список:

Способы взаимодействия классов

  • Наследование
  • Ассоциация
    • Агрегация (подвид Ассоциации)
    • Композиция (подвид Ассоциации)

Уже попроще, тк понятна структура терминов. Теперь давайте разберемся с каждым по отдельности

Наследование

Это один из принципов ООП, который подразумевает, что класс наследник, будет иметь все те же свойства и методы, что и в базовом классе. В коде это выглядит так:

<?php

class A {
    public function helloWorld(){
        echo 'Hello world';
    }
}

class B extends A {}

$obj = new B;
$obj->helloWorld();

Т.е. класс B - наследник класса A. Ему достался метод helloWorld, который он может вызвать сразу или переопределить, а потом вызвать.

Как следует из ключевого слова extend, используется для расширения возможностей базового класса. Со стороны программиста, это может потребоваться для переопределения какого-либо метода или для добавления какой-нибудь новой логики.

Это классика ООП, поэтому думаю с понимаем проблем не должно быть.

Ассоциация

Ассоциация, как следует из название, это способ взаимодействия, когда один класс ассоциируется с другим. Т.е. один класс использует внутри своей реализации свойства или методы объекта другого класса. Просто запомните, что в отличии от наследования, ассоциации не РАСШИРЯЮТ класс, а ИСПОЛЬЗУЮТ объект другого класса. Дальше мы это увидим на примерах, а пока надо упомянуть, что ассоциации бывают двух видов: Композиция и Агрегация.

Композиция

Это ассоциация, при которой используемый объект создается внутри класса. Простой пример:

<?php

class A {
    public function helloWorld(){
        echo 'Hello World';
    }
}

class B {
    protected $a;
    public function __construct(){
        $this->a = new A;  // создает объект другого класса
    }
    public function sayHello(){
        $this->a->helloWorld();  // использует объект другого класса
    }
}

$obj = new B;
$obj->sayHello();

Тут мы видим, что в конструкторе класса B, создается объект класса A. И дальше используется в методе sayHello.

Композиция - это по сути включение класса, внутрь другого класса с помощью создания объекта внутри этого класса.

У такого подхода есть один огромный недостаток - сильная связанность, это значит, что для того чтобы поменять класс A на A1 вам придется переписывать конструктор (new A1 вместо A).

Преимущество у такого способа, это то, что класс B, управляет временем жизни объекта A. Т.е. при удалении объекта B будет и удален, объект A который был создан внутри B.

Агрегация

Это ассоциация, при которой используемый объект создается вне класса. Простой пример:

<?php

class A {
    public function helloWorld(){
        echo 'Hello World';
    }
}

class B {
    protected $a;
    public function __construct(A $a){
        $this->a = $a;
    }
    public function sayHello(){
        $this->a->helloWorld();  // использует объект другого класса
    }
}

$objA = new A; // создает объект другого класса

$objB = new B($objA);
$objB->sayHello();

Тут мы видим, что создается объект класса A, а заетм он передается извне в конструктор класса B. И дальше используется в методе sayHello.

Агрегация - это по сути включение класса, внутрь другого класса с помощью передачи объекта внутрь этого класса.

В отличие от композиции, тут все наоборот. Преимущество: легко передать новый объект A1 без изменений в коде - слабая связанность. Из недостатков, пожалуй, следует отметить, что в больших системах это приводит к огромному кол-ву переменных в конструкторе (хороший пример этой проблемы был в Magento 2.0.0, к счастью сейчас это уже убрали).

Заключение

Подведем итоги по способам взаимодействия классов:

  • Наследование - класс наследует поля и методы родительского класса
  • Ассоциация
    • Композиция - класс создает объект другого класса внутри себя и использует его поля и методы
    • Агрегация - класс получает объект другого класса из вне и использует его поля и методы

Если остались вопросы, пишите в комментариях.

P.S. Обозначение на блок схемах

Совсем забыл про обозначение способов взаимодействия на блок схеме, выглядит это так

Обозначение взаимодействия классов

Категории: PHP Собеседования