Задать вопрос
eucalipt
@eucalipt
Самоделкин.

Какова роль интерфейсов в ООП?

Никак не могу въехать, зачем нужны эти интерфейсы.
В документации четко написано, что нужны они для определения методов и свойств, которые должен содержать определенный класс.
Но смысл? Зачем мне создавать файл, контролирующий это, если я и сам могу контролировать то, какие методы у меня есть, а каких нет?
Может создано это для работы в больших коллективах? Но ведь тогда любой участник сможет поправить и интерфейс.
  • Вопрос задан
  • 6114 просмотров
Подписаться 28 Оценить 1 комментарий
Решения вопроса 2
Приведу пример на коленке. Хотим, например, написать абстрактную файловую систему. Для начала, определим интерфейс, для ФС:

interface FileSystemInterface {
  public function write($file, $data);
  public function read($file);
}


Затем, хочу реализацию интерфейса ФС для работы с файликами:

class OSFileSystem implements FileSystemInterface {
  public function write($file, $data) {
     // открываем файлик, пишем данные
  }

  public function read($file) {
    // открываем файлик, возвращаем данные
  }
}


Вдруг, кому-то захотелось файловую систему в облаке. Окей, не проблема, реализуем это:
class CloudFileSystem implements FileSystemInterface {
  public function write($file, $data) {
     // открываем соединение с облаком, пишем данные
  }

  public function read($file) {
    // открываем соединение с облаком, возвращаем данные
  }
}

Пусть у нас есть кой-то код, работающий с файловой системой, назовем его "Хранилище файлов". Пусть он выглядит примерно так:

class FileStorage {
  protected $Fs;
  
  public function __construct(FileSystemInterface $Fs) {
    $this->Fs = $Fs;
  }  

  public function saveFile() {
    $this->Fs->write('file.txt', 'file data');
  }

  public function getFile() {
    return $this->Fs->read('file.txt', 'file data');
  }
}


Отлично! Теперь мы можем хранилищу файлов отдать любой объект с реализованным интерфейсом FileSystemInterface. Пример:

// Хранилище файлов работает с файловой системой ОС:
$FS = new OSFileSystem();
$FileStorage = new FileStorage($Fs);
$FileStorage->getFile();

// Хранилище файлов работает с файловой системой в облаке:
$FS = new CloudFileSystem();
$FileStorage = new FileStorage($Fs);
$FileStorage->getFile();


Использование интерфейса, в данном случае. позволяет нам писать только реализацию работы файловой системы, а бизнес-логика, работающая с файловой системой никак не меняется, она знает, что в любом случае файловая система реализует интерфейс FileSystemInterface и может без опаски использовать методы этого интерфейса.
Ответ написан
Много ответов есть уже, лучше попробую идти рядом с вашими словами. Итак,
> Зачем мне создавать файл, контролирующий это, если я и сам могу контролировать то, какие методы у меня есть
Вы - это ваша голова, вы человек, не робот, ваш может не быть на работе например, или вы сами можете забыть, как у вас взаимодействуют части системы. Интерфейсы - это в общем-то тоже документация. И не нужно строго различать "чисто интерфейсы", и интерфейсы класса - те методы, которые у класса паблик - это точно такой же интерфейс, только он явно не отделен от класса. Когда у класса всего 3-4 метода, и все они связаны простой идеей, то и выделять ничего не надо. Когда у класса уже 10 методов, и среди них есть небольшие смысловые группы, то уже имеет смысл эти группы подчеркнуть. И, в конце концов, вместо каши из 10 методов, вы читаете следующее: class Graph : IEnumerable, IIndexable, IDrawable - и вы знаете, что ваш граф перечисляется, индексируется и рисуется. Это уже очень много информации, вы уже понимаете, как взаимодействуют части вашей системы.

> Может создано это для работы в больших коллективах? Но ведь тогда любой участник сможет поправить и интерфейс.
Да, совершенно верно, для больших коллективов. Нет, участник просто так не сможет поправить интерфейс, не побеседовав с остальными. В лучшем случае участнику придется поправить весь код, который "висит" на этом интерфейсе, в худшем - он в принципе ничего не сможет поменять, если интерфейс "публичный" и используется несколькими командами разработчиков. Классический пример - системы плагинов. Если к MS Word-у уже написано куча плагинов, то MS не может взять и просто так поменять ифейсы, не поломав совместимость. Хотя некоторые аспекты реализации - может. Потому что, как уже сказали выше, интерфейс - это ДОГОВОР. Чем БОЛЕЕ он стабилен, тем ЛУЧШЕ. Команды договариваются (!), создавая интерфейсы, чтобы потом было как можно МЕНЬШЕ конфликтов и разногласий, т.к. проблемы с интерфейсом затрагивают всех. Найдите любую команду от 30 человек, и вы увидите, насколько это все важно.

Еще две вещи напоследок:
1) интерфейсы из ОО языков лишь частный пример понятие интерфейса в жизни вообще. Вы же, когда покупаете SATA-диск, наверное рассчитываете, что сможете его подключить к своему компу? А с чего вы взяли? А, ну конечно, ведь на упаковке написано SATA - значит производитель соблюдает ДОГОВОР - интерфейс передачи данных;
2) необходимость в некоторых фичах языков сложно осознать в личных проектах и даже в маленьких командах. Это тоже как в жизни: свой дом, как говорится, должен построить каждый мужик, а чтобы построить бизнес-центр или высотку, нужны определенные знания, т.к. другие масштабы. Это нормально. Тем не менее, нужно читать и искать примеры. Хотя современные ОО-языки и сами дают много примеров. Раз у вас PHP, почитайте про Iterator например.
Ответ написан
Пригласить эксперта
Ответы на вопрос 6
Дело нехитрое. Нужда в интерфейсах возникает, когда над кодом начинает работать более 1 человека. Себя, Матвей, вы контролировать можете, коллегу – уже в меньшей степени.
Еще печальней дела обстоят, когда вы выпускаете код, который может быть расширен неизвестно кем, неизвестно с какой целью (фреймворки). Очевидно, вам захочется сообщить будущим пользователям вашего кода, как конкретно этим кодом следуе пользоваться. Именно эту задачу решают интерфейсы.

Напоследок скажу вам, что ваше сознание не статично. Через 3 года Матвей тогдашний будет сильно отличаться от Матвея сегодняшего. И будущий Матвей будет чрезвычайно признателен Матвею сегодняшнему, если правила пользования его за 3 года страсть как разросшегося кода будут по-прежнему аккуратно систематизированы в том числе с помощью интерфейсов.
Ответ написан
Комментировать
@iliyaisd
Пример из реальной жизни. У меня есть система, которая работает с несколькими системами оплаты. При этом в некотором месте я не знаю, какая именно система мне понадобится, я это определяю динамически и создаю класс плательщика и работаю с ним дальше.

IPayer payer = this.getPayer((String) payments.get(i).getSystemCode());
payer.processPayment(payments.get(i));


Во-первых, чисто синтаксически это невозможно сделать без интерфейсов. Во-вторых, я в этом месте вообще не думаю, о том, что там кто платит и по какой механике, и при этом абсолютно уверен, что всё отработает правильно, потому что все плательщики наследуют один интерфейс и отдают данные по одному принципу. Это как если вы покупаете зарядку на microUSB (к примеру) и точно знаете, что она подойдёт к вашему телефону.
Ответ написан
Комментировать
@vilgeforce
Раздолбай и программист
Унаследован от интерфейса, имеется экземпляр этого класса, собралось без проблем - интерфейсу удовлетворяет. И не надо руками проверять что у класса есть все 200 необходимых методов, что все они имеют нужные прототипы, что все они реализованы. Особенно полезно, когда классов должно быть несколько десятков.
Ответ написан
Комментировать
@serega_kaktus
Программист-самоучка, фрилансер
Во фреймворках, больших проектах интерфейсы описывают набор обязательных методов, которые в дальнейшем в коде стопроцентно используются. Таким образом, если разработчик Вася захочет написать какой-то свой плагин, например, для работы с юзерами, то он будет точно знать, какие методы он должен в своем классе реализовать. Если же не будет интерфейса, то Вася не будет знать, какие именно методы нужно реализовать, забудет про один маленький метод, а на продакшне потом выскочит исключение.

Абстрактные методы в абстрактном классе играют ту же роль, что и интерфейс - описывают набор обязательных методов. Но при этом в абстрактном классе можно реализовать некоторые методы, которые в скорее всего будут одинаковы для многих потомков (хотя бы для 2х). Таким образом избегаем копипаста в коде
Ответ написан
@F1NaL
Вы сами дали себе ответ.
Интерфейсы как раз и сделаны для работы нескольких разработчиков над 1 проектом.
Чтобы разработчиком не приходилось договариваться голосом, они описывают так называемые "договоры". Т.е если мой класс реализует такой то интерфейс, то в нем должны быть такие то методы.
Ответ написан
trevoga_su
@trevoga_su
> Но ведь тогда любой участник сможет поправить и интерфейс.

Вы не должны править основной код системы без согласия его разработчиков. Или у вас попросту нет этой возможности - закрыт доступ.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы