Interfejsy warto stosować jako type-hint parametru metody, która oczekuje pewnych zależności płynących z tego parametru. Jest to wymuszenie i pewien kontrakt między programistami pracującymi w danym projekcie. A nawet i sobą samym, ponieważ po jakimś czasie możesz zapomnieć o tym, że musisz dostarczyć funkcji jakieś zależności. W momencie testowania gdy zapomnisz uwzględnić danego przypadku, to na produkcji może dojść do błędów. Jeżeli oczekujesz interfejsu a go nie dostaniesz, to po odświeżeniu strony od razu się dowiesz o tym że tego nie zrobiłeś i po prostu podepniesz interfejs pod klasę i zaimplementujesz metody.
Teraz przykład. Załóżmy, że chcesz napisać program, w którym będziesz sterował pojazdem. Implementacja mogłaby wyglądać w ten sposób.
class Car
{
public function turnLeft(): void
{
// code
}
}
class Program
{
public function main($car): void
{
$car->turnLeft();
}
}
Ale nie mamy pewności czy aby na pewno zmienna car w metodzie main() posiada taką funkcje jak turnLeft(). Może to prowadzić do błędów. Aby się upewnić że możemy takiej metody użyć, moglibyśmy zapisać to w ten sposób.
class Car
{
public function turnLeft(): void
{
// code
}
}
class Program
{
public function main(Car $car): void
{
$car->turnLeft();
}
}
Teraz jest już lepiej, ale i tak nie jest to dobrze zbudowana aplikacja. Co jeżeli chcielibyśmy dodać sterowanie innym pojazdem do naszej funkcji main() ? Może zamiast typowania parametru jako Car, powinniśmy pomyśleć o czymś czego dana metoda wymaga do działania, a niekoniecznie martwić się o mechanizmy, które potrzebuje aby była wykonana? W myśl 5 zasady SOLID, parametry powinniśmy uzależniać od abstrakcji.
interface Vehicle
{
public function turnLeft(): void
}
class Car implements Vehicle
{
public function turnLeft(): void
{
// code
}
}
class Motocycle implements Vehicle
{
public function turnLeft(): void
{
// code
$this->cośTuMuszęPoliczyć();
}
private function cośTuMuszęPoliczyć()
{
// code
}
}
class Program
{
public function main(Vehicle $vehicle): void
{
$vehicle->turnLeft();
}
}
Tutaj abstrakcja jest dosyć powiązana i zamiast interfejsu Vehicle moglibyśmy zrobić klasę abstrakcyjną z abstrakcyjną metodą turnLeft()
Jeżeli używasz IDE np PHPStorm, to dodatkowo zyskasz podpowiedzi co dana zmienna zawiera.