Обычно интерфейсы используются для определения контрактов, поэтому вы получаете проверку типов. Существует также стиль программирования, называемый «программирование на интерфейсах», что является хорошей идеей. См. Принцип обращения зависимостей :
A. Модули высокого уровня не должны зависеть от модулей низкого уровня. Оба должны зависеть от абстракций.
B. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций. "
Таким образом, если вы определяете функции и методы, вместо подсказки типа для классов, вы просто намекаете на интерфейсы.
Вот пример. Допустим, вы определяете интерфейсы для входных и выходных потоков следующим образом:
interface OutputStream{
write($string); // Writes a string to the output.
close(); // Closes the output stream.
}
interface InputStream{
read($length); // Reads at most $length characters.
eof(); // TRUE, if the input stream is empty.
}
Теперь вы можете создать copy
функцию или метод, который копирует весь вывод потока на вход, не имея ни одного из них:
// 50 is just chosen randomly.
function copy(InputStream $input, OutputStream $output){
while(!$input->eof()){
$output->write($input->read(50));}}
Поздравляем, ваша реализация copy
теперь работает для каждой комбинации входного и выходного потока, даже не реализуя ее.
Абстрактные классы, с другой стороны, могут использоваться для реализации общих функций без необходимости реализации полностью функционального класса.
Опять пример. Допустим, вы хотите иметь выходные потоки. Вам нужен метод write($s)
, который записывает строку в вывод, и вам нужен метод writeLine($s)
, который записывает строку и дополнительный символ новой строки в вывод. Тогда это будет уместно:
abstract class AbstractOutputStream{
public function writeLine($s){
$this->write($s."\n");}}
Конкретные выходные потоки теперь могут наследоваться от абстрактного выходного потока, реализовать только write
и получить writeLine
бесплатно!