Delegation vs. Forwarding in OOP

Най-просто идеята и на двете е, когато извикаме метод на един клас, той от своя страна да извика метод от друг клас, който реално да свърши работата. Разликата е как става това.

class RealPrinter  // the "receiver"
{
    public function print(): void
    {
        echo "Hello world!\n";
    }
}

class Printer  // the "sender"
{
    private RealPrinter $p;

    public function __construct()
    {
        $this->p = new RealPrinter();  // create the receiver 
    }

    public function print(): void
    {
        $this->p->print();  // calls the receiver
    }
}

// to the outside world it looks like Printer actually prints
$printer = new Printer();
$printer->print();

Горният пример, (макар и нарушаващ Inversion of Control), е пример за Delegation, защото, когато искаме от обект на Printer да свърши нещо, той създава друг обект, чиито метод върши исканото действие и тогава го връща сякаш той го е свършил.
Викащият няма как да знае кой реално е свършил работата.

Но по-същественото е, че двата класа реално погледнато нямат никакво отношение по между си, освен, че единият създава обект от другия (или му го инджектват отвън) за да го използва за да му свърши работата.
Printer не е наследник на RealPrinter, нито обратното, те не се знаят един друг.

Ако имахме наследяване, щяхме да имаме Forwarding, защото и без да създаваме специално друг обект, на който да делигираме да свърши работата, вече ще имаме такъв – аналогичният метод от родителският клас, освен разбира се ако не е private.

Затова още се казва, че класът Printer е „wrapper“, a RealPrinter е „wrapee“, тоест eдиният е „опаковката“, другият е „съдържанието“.

Composition over Inheritance

Това е начин за цялостна организация на отделните класове в ООП, според който класовете не трябва да се наследяват един друг и така да постигат code reuse, полиморфизъм…, а да се съдържат един в друг, тоест, като даден клас съдържа като пропъртита – обекти от други класове.

Едно от предимствата на този модел е, че системата става по-гъвкава, може да сдържа по-разнородни елементи, за разлика от Inheritance моделът, при който системата от класове напомня повече на „родословно дърво“.

It is more natural to build business-domain classes out of various components than trying to find commonality between them and creating a family tree.

Да си спомним от реалният живот, как например обектът от клас Car, може да съдържа много обекти от различни класове като Tyres, Engine, Brakes… които няма нужда да наследяват Car.

Operator polymorphism

Полиморфизъм, основан на това, че една и съща операция от чисто семантична гледна точка (а не математическа), може да извършва различни действия и да създава различен краeн резултат, в зависимост от операндите.

Например под операцията събиране може се има предвид конкатениране на стрингове ако подaдем стрингове, може да знaчи аритметическо събиране ако имаме числа… и т.н…

Затова казвамe, че се има предвид семантичнният смисъл на операцията, а не чисто математическият.

Добър пример за Operator polymorphism е например Ad hoc polymorphism, по-известен като function overloading.
Koeто означа, че следователно можем да причислим Operator polymorphism към Static polymorphism.