W3docs

interface

Ключевое слово «interface» в PHP используется для определения набора методов, которые класс обязан реализовать. Синтаксис и примеры использования.

Ключевое слово PHP interface

Интерфейс — это контракт: он перечисляет методы, которые класс обязан предоставить, не указывая, как они работают. Любой класс, использующий implements, обязуется определить каждый объявленный метод. Это позволяет программировать исходя из возможности («всё, что можно записать в лог», «всё, что можно сериализовать»), а не исходя из конкретного класса.

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

На этой странице рассматривается, как объявлять интерфейс, реализовывать один или несколько, совместно использовать константы, расширять интерфейсы и проверять типы во время выполнения с помощью instanceof. Если вы только начинаете работать с объектами в PHP, начните с классов и объектов PHP и что такое ООП.

Синтаксис

Вот базовый синтаксис объявления интерфейса:

interface MyInterface {
  public function someMethod();
}

Здесь объявляется интерфейс MyInterface с единственным методом someMethod(). Ключевые правила:

  • Тела методов опускаются — интерфейс объявляет только сигнатуры, каждая из которых заканчивается точкой с запятой.
  • Все методы неявно являются public; можно написать public для ясности, но другие модификаторы доступа не допускаются (private/protected запрещены).
  • Класс принимает интерфейс с помощью ключевого слова implements и должен определить каждый метод, иначе PHP выбрасывает фатальную ошибку.

Примеры

Рассмотрим несколько практических примеров использования ключевого слова interface. Первый класс реализует один интерфейс; второй — сразу два (разделённых запятой):

<?php

// Example 1
interface MyInterface {
  public function someMethod();
}
class MyClass implements MyInterface {
  public function someMethod() {
    echo "This is from someMethod." . PHP_EOL;
  }
}

$obj = new MyClass();
$obj->someMethod();

// Output: This is from someMethod.

// Example 2
interface MyOtherInterface {
  public function someOtherMethod();
}
class MyOtherClass implements MyInterface, MyOtherInterface {
  public function someMethod() {
    echo "This is from someMethod." . PHP_EOL;
  }
  public function someOtherMethod() {
    echo "This is from someOtherMethod." . PHP_EOL;
  }
}

$obj2 = new MyOtherClass();
$obj2->someMethod();
$obj2->someOtherMethod();

// Output:
// This is from someMethod.
// This is from someOtherMethod.

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

Константы интерфейса

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

<?php

interface HttpStatus {
  const OK = 200;
  const NOT_FOUND = 404;
}

class Response implements HttpStatus {
  public function describe(): string {
    return "Status " . self::OK;
  }
}

echo (new Response())->describe() . PHP_EOL;
echo HttpStatus::NOT_FOUND . PHP_EOL;

// Output:
// Status 200
// 404

Для констант, которые можно переопределять, используйте константы класса внутри класса.

Расширение интерфейсов

В отличие от классов, интерфейс может extend несколько других интерфейсов. Комбинированный интерфейс требует все методы каждого родителя:

<?php

interface Readable {
  public function read(): string;
}

interface Writable {
  public function write(string $data): void;
}

// A single interface that demands both capabilities
interface ReadWrite extends Readable, Writable {}

class File implements ReadWrite {
  private string $buffer = "";
  public function read(): string { return $this->buffer; }
  public function write(string $data): void { $this->buffer = $data; }
}

$f = new File();
$f->write("hello");
echo $f->read() . PHP_EOL;

// Output: hello

Так PHP симулирует множественное наследование — см. наследование PHP для одиночного наследования классов с помощью extends.

Подсказки типов и instanceof

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

<?php

interface Shape {
  public function area(): float;
}

class Circle implements Shape {
  public function __construct(private float $r) {}
  public function area(): float { return 3.14159 * $this->r ** 2; }
}

function printArea(Shape $shape): void {
  echo round($shape->area(), 2) . PHP_EOL;
}

$c = new Circle(2);
printArea($c);
var_dump($c instanceof Shape);

// Output:
// 12.57
// bool(true)

Интерфейс vs. абстрактный класс

Оба определяют контракт, но решают разные задачи:

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

Если нужно совместно использовать код между классами без наследования, обратитесь к трейтам.

Преимущества

Использование ключевого слова interface даёт несколько преимуществ:

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

Заключение

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

Практика

Практика
Какова цель интерфейса в PHP?
Какова цель интерфейса в PHP?
Was this page helpful?