Интерфейсы в PHP: пример из практики

Иногда у вас есть группа классов, которые не обязательно связаны наследованием. У вас могут быть совершенно разные классы, которые просто имеют общие черты поведения. Классический пример: банку и дверь можно открывать и закрывать, но они никак не связаны между собой. Независимо от типа банки или двери, они оба могут выполнять эти действия, но другого общего между ними нет.

Что делает интерфейс?

Интерфейс позволяет указать, что объект способен выполнение определенной функции, но это не обязательно говорит вам, как объект делает это. Интерфейс является контрактом между несвязанными объектами для выполнения общей функции. Объект, который реализует этот интерфейс гарантирует своим пользователям, что он способен выполнять все функции, определенные спецификация интерфейса. Велосипеды и футбольные мячи — совершенно разные вещи, но объекты, представляющие их предметы в системе инвентаря магазина спортивных товаров должны быть способны взаимодействовать с этой системой.

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

interface Openable {
    public function open();
    public function close();
}

Вы объявляете интерфейс Openable, используя синтаксис, аналогичный синтаксису класса, за исключением того, что вы заменяете слово class на interface. Интерфейс не имеет свойств и не имеет реализации своих методов.

Поскольку реализация не указана, вы фактически объявляете эти методы абстрактными. Это говорит PHP что любой класс, реализующий этот интерфейс, отвечает за обеспечение реализации метода. Если вы не предоставите реализацию всех абстрактных методов интерфейса, PHP будет выдавать ошибку во время выполнения. Вы не можете выборочно выбирать некоторые абстрактные методы для реализации, — вы должны обеспечить реализацию их всех.

Интерфейс Openable — это контракт с другими частями приложения, в котором говорится, что любой класс, реализующий этот интерфейс предоставляет два метода, называемых open() и close(), которые не принимают параметров. С этим согласовано — при наборе методов вы можете позволить очень разным объектам вызвать один и тот же метод без необходимость наследственных отношений между ними.

class Door implements Openable {
	private $_locked = false;
	public function open() {
		if($this->_locked) {
			print "Can't open the door. It's locked.";
		} else {
			print "creak...";
		}
	}
	public function close() {
		print "Slam!!";
	}
	public function lockDoor() {
		$this->_locked = true;
	}
	public function unlockDoor() {
		$this->_locked = false;
	}
}
class Jar implements Openable {
	private $contents;
	public function __construct($contents) {
		$this->_contents = $contents;
	}
	public function open() {
		print "the jar is now open";
	}
	public function close() {
		print "the jar is now closed";
	}
}

function openSomething(Openable $obj) {
	$obj->open();
}
$objDoor = new Door();
$objJar = new Jar("jelly");
openSomething($objDoor);
openSomething($objJar);

Поскольку и класс Door, и класс Jar реализуют интерфейс Openable, вы можете применить к ним обоим функцию openSomething(). Потому что эта функция принимает только то, что реализует имплементируемый интерфейс, а вы знаете, что можете вызывать методы open() и close() внутри него. Тем не менее, вы не должны пытаться получить доступ к свойству содержимого класса Jar или использовать lock () или метод unlock() класса Door внутри функции openSomething(), потому что это свойство и эти методы не являются частью интерфейса. Контракт интерфейса гарантирует, что у вас есть open() и close() и ничего больше.

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *