Interfejs może być własnym typem, oznaczającym obiekt dowolnej klasy implementującej dany interfejs. Poznajmy tę sztuczkę programowania obiektowego!
Oto interfejs i dwie klasy implementujące go:
<?php
declare(strict_types=1);
interface RuleInterface
{
public function validate(array $data, string $field, array $params): bool;
public function getMessage(): string;
}
class UrlRule implements RuleInterface
{
public function validate(array $data, string $field, array $params): bool
{
return (bool) filter_var($data[$field], FILTER_VALIDATE_URL);
}
public function getMessage(): string
{
return "Invalid URL";
}
}
class EmailRule implements RuleInterface
{
public function validate(array $data, string $field, array $params): bool
{
return (bool) filter_var($data[$field], FILTER_VALIDATE_EMAIL);
}
public function getMessage(): string
{
return "Invalid email";
}
}
Piszemy funkcję, która przyjmie obiekt dowolnej klasy i wyświetli jego metodę getMessage:
<?php
declare(strict_types=1);
interface RuleInterface
{
//(...)
}
class UrlRule implements RuleInterface
{
//(...)
}
class EmailRule implements RuleInterface
{
//(...)
}
function message(UrlRule|EmailRule $rule) {
echo $rule->getMessage();
}
$emailRule = new EmailRule();
$urlRule = new UrlRule();
message($emailRule);
message($urlRule);
Użyliśmy typu „unijnego” pozwalając na przekazanie obiektu typu UrlRule albo EmailRule. Nie jest to bardzo praktyczne.
Zamiast tego, możemy użyć jako typ nazwę interfejsu:
<?php
declare(strict_types=1);
interface RuleInterface
{
//(...)
}
class UrlRule implements RuleInterface
{
//(...)
}
class EmailRule implements RuleInterface
{
//(...)
}
function message(RuleInterface $rule) {
echo $rule->getMessage();
}
$emailRule = new EmailRule();
$urlRule = new UrlRule();
message($emailRule);
message($urlRule);
Teraz nasza funkcja może przyjąć dowolny obiekt, pod warunkiem, że jest to obiekt klasy implementującej interfejs RuleInterface.
Używanie interfejsów jako typów strasznie ułatwia pisanie obiektowego kodu.