Robustness principle

Известен също и като Arrow rule или Postel’s law.

Можем да заменим метод от родителски обект, с метод от наследник, ако методът на наследника е по-либерален откъм входни параметри, и по-консервативен откъм изходен резултат.

Но не и обратното.

Be conservative in what you do, be liberal in what you accept from others.

Литература:

https://en.wikipedia.org/wiki/Robustness_principle

https://medium.com/kubo/postels-law-designing-for-robustness-1503ff1f72dd

Static and dynamic polymorphism

Още са известни като Compile time polymorphism (static binding) и Runtime polymorphism (dynamic/late binding).

Това са видове полиморфизъм според това КОГА се случват, демек compile time или runtime. В какъв смисъл? В смисъл кога изпълнението на програмата ще извика по даден сигнъчър на функцията – един код, кога друг.

Динамичните – runtime, a Статичните – compiletime.

Даже по-правилно е Static polymorphism да бъде наричан Static binding, и съответно Dynamic polymorphism – Dynamic binding.

Но какво изобщо е binding?
The process of replacement of the method call with method definition is called as binding.
Или още – като извикаме функция с дадено име, параметри и тип на резултата, коя точно функция да извикаме и изпълним.
Binding е „връзката“ между извикването и дефиницията, или по-точно, като извикаме това и това, кой код реално ще се изпълни.

Например Ad hoc (или още Overloading) се случва compile time, защото тогава програмата решава коя от всички функции с еднакво име, ще бъде извикана runtime, на база на подадените аргументи. Демек – ясно се вижда – при даден сигнъчър какво да се изпълнява. Затова е Static binding или oще Static polymorphism.
The compiler looks at the method signature and decides which method to invoke for a particular method call at compile time.

Compile time polymorphism (static binding) and Runtime polymorphism (dynamic binding). Method overloading is an example of static polymorphism, while method overriding is an example of dynamic polymorphism.

Dynamic binding (Dynamic polymorphism) имаме например при оверрайдване на методи:

class SomeParent
{
    public function sayHello(): void
    {
        echo 'I am parent';
    }
}

class SomeChild extends SomeParent
{
    public function sayHello(): void
    {
        echo 'I am child';
    }
}

(new SomeParent)->sayHello();    // I am parent
(new SomeChild)->sayHello();     // I am child

Защо имаме динамичен, а не статичен? Не е ли и в този пример зададено още compiletime кога кой метод да извика?
Защото тънкостта е, че като имаме оверрайдване все едно казваме на самият компилатор „за този метод, имам версия тук, имам версия там… коя ще ми трябва, още не знам“. Самата идея на оверрайдването е такава – да НЕ се знае предварително коя точно „версия“ на метода ще ни трябва.

Ще попитате, „добре де, така написано, компилаторът не му ли става ясно кога кой метод да извика?“
Явно не, защото докато не инстанцираме обектите, което става runtime, няма как да знаем кой точно да извикаме. Демек, той методът е един, не са два или повече, просто няма как да направим самата връзка между извикването и това кое да извикаме, докато нямаме обект-викач, който да го извика.
The version of a method that is executed will be determined by the object that is used to invoke it.
Докато няма родителски и детски обекти, няма как да знаем чия „версия“ на метода да извикаме.

method overloading is an example of compile time/static polymorphism because method binding between method call and method definition happens at compile time and it depends on the reference of the class (reference created at compile time and goes to stack).

method overriding is an example of run time/dynamic polymorphism because method binding between method call and method definition happens at run time and it depends on the object of the class (object created at runtime and goes to the heap).

Method Overloading is an example of static polymorphism.
Method Overriding is an example of dynamic polymorphism.

Static Polymorphism achieved through static binding.
Dynamic Polymorphism achieved through dynamic binding.

Static Polymorphism happens in the same class.
Dynamic Polymorphism happens between different classes.

Object assignment is not required for static polymorphism.
It is required where a subclass object is assigned to super class object for dynamic polymorphism.

Inheritance not involved for static polymorphism.
Inheritance involved for dynamic polymorphism.

Работата е там, че при оверлоудване имаме съвсем различни функции/методи но с ЕДНО ИМЕ.

При оверрайдване имаме ЕДНА функция/метод, в отделни наследяващи се класове, но просто все още не сме решили коя от тях да извикаме. А ще решим на база това кой от класовете инстанцираме или използваме статично. Демек, няма как предварително, при компилиране, компилаторът да знае коя версия на тази ЕДНА функция ще извикаме.

Демек, при оверлоудване предварително, на база сигначъра казваме на компилатора „може тази функция/метод да се казва винаги еднакво, но ако я извикаш с тези и тези аргументи и тип резултат – извикваш тази, ако я извикаш с тези и тези аргументи и тип резултат – извикваш онази.“ На база различният сигнъчър, дори и имената да са еднакви, компилаторът знае коя кое да извика предварително.
Всичко е ясно зададено предварително. На база сигнъчър.

Не е така с оверрайдването. Там коя точно версия на функцията/метода ще се извика, се случва рънтайм.

Демек, при оверрайдването идеята е да предоставим предварително N на брой „версии“ на даден метод, но чак рънтайм да решим коя точно да извикаме. Демек, байндингът да стане динамично.

Литература:

https://stackoverflow.com/questions/20783266/what-is-the-difference-between-dynamic-and-static-polymorphism-in-java

https://www.sitepoint.com/quick-guide-to-polymorphism-in-java/

https://en.wikipedia.org/wiki/Method_overriding