Как использовать классы через интерфейсы?

Смотрю ролики по программированию. Заинтересовали ролики Немчинского (хотя некоторые вещи он объясняет крайне непонятно для новичка).
Во многих роликах Немчинский говорит, что надо использовать классы через интерфейсы.
Например в этом ролике
Я не понимаю проблемы и не понимаю смысла этого действия.

У меня есть класс 1, в нем есть методы. Класс 1 используется в классе 2. Зачем интерфейс?
И как через него использовать классы?

Интерфейс - это "контракт", список методов обязательных для реализации.
Например, у нас есть класс MySQLBase и класс MSSQLBase. Мы знаем, что у любой бд нужна возможность подключения и создаем интерфейс IBase с методом ConnectToBase.
И далее реализуем его в классах MySQLBase и класс MSSQLBase. Теперь любой программист знает, что в каждом из классов есть метод ConnectToBase, а если его вдруг нет...то что то изменилось в интерфейсе (что обычно бывает редко).

Как использовать классы через интерфейсы? Обычные классы, при наследовании и зачем это?
Можно привести пример на php и показать выгоду такого подхода?
  • Вопрос задан
  • 170 просмотров
Пригласить эксперта
Ответы на вопрос 5
Real_Fermer
@Real_Fermer
Программист PHP
на двух классах вы не поймете зачем нужны интерфейсы. и выгоды от их использования.
Интерфейсы нужны когда вы закладываете возможность расширения вашей системы. И расширять будете не вы.
Ответ написан
mayton2019
@mayton2019
Bigdata Engineer
Смотрю ролики по программированию. Заинтересовали ролики Немчинского (хотя некоторые вещи он объясняет крайне непонятно для новичка).

Немчинский - популист и популяризатор своей собственной it-школы. Обычно в каждом видосе - реклама.

У него есть контр-образовательная позиция. Он например считает что после 1 курса универа надо сразу идти работать и наплевать на диплом вообще.

Во многих роликах Немчинский говорит, что надо использовать классы через интерфейсы.
....
У меня есть класс 1, в нем есть методы. Класс 1 используется в классе 2. Зачем интерфейс?

Не смотрел видео. Но в этом вобщем-то есть смысл для создания слабой зацепленности и InversionOfConrol.
Новичку такое объяснить нельзя. Нужны месяцы и годы чтобы понять. Желательно не на синтетических
уроках а на реальных боевых проектах где МНОГО кода. Именно обилие кода и требование проводить
сложны рефакторинги, замены движков одни на другие и цикл постоянной доработки - мотивируют к
внедрению базовых интерфейсов вместо классов.

То что ты не понял с 1 раза - это нормально. Я тоже когда изучал ооп и полиморфизм на примере Borland Pascal
тоже подумал что это туфта и я это использовать никогда не буду ибо незачем.

Можно привести пример на php и показать выгоду такого подхода?

Тут я не уверен. Вроде в PHP OOP есть с 5 версии. А есть ли там механики полиморфизма - ХЗ.
Пускай знающие прокоментируют. Но если есть - то хороший пример переключения
функционала например с Db MySQL на Postgresql без переписывания бизнес-логики.
В идеале у вас переключение должно произойти в 1 строчке кода. Если удалось - значит
метод работает.
Ответ написан
@res2001
Developer, ex-admin
А теперь развейте вашу мысль с классами MySQLBase и класс MSSQLBase.
Вы хотите сделать универсальный адаптер, который будет работать с любой БД. Он принимает на вход ссылку на IBase и спокойно вызывает метод ConnectToBase, не заботясь о том, что там в реальности MySQLBase или MSSQLBase.
Ответ написан
Комментировать
DollyPapper
@DollyPapper
Суть в том, что как вы и сказали: интерфейс это контракт. Можно его еще назвать "тип". Т.е. завязываясь на интерфейс мы обязуем вызывающий код передать нам штуку которая умеет делать определенный список вещей. Собственно все. Немного не правильно противопоставлять интерфейсы наследованию. Наследование это когда одна штука является спицифичной версией другой штуки. Интерфейс же в свою очередь это больше клиентская часть, когда код говорит - я хочу на вход переметр такого-то типа. Давайте простой высосаный из пальца, но довольно ясный пример:
Есть класс Parser
class Parser
{
	public function getPage($url){
		return $this->load($url);
	}
	protected function load($url){
		return file_get_contents($url);
	}
}

Есть класс Exchanger
class Exchanger extends Parser
{
	public function getRate($currency){
		return $this->load('...?id=' . $currency);
	}
}

В примере выше в классе Exchanger мы унаследовали метод load из базового класса. Дальше используем
$parser = new Parser();
$parser->getPage('...');

$exchanger = new Exchanger();
$exchanger->getRate('USD');

Т.е. и там и там должен быть метод load который по http что-то откуда-то грузит и выдает данные которые дальше как-то используются и т.к. метод load уже есть в классе Parser, ну мы просто унаследовали его и все работает. Но при таком подходе появляются проблемы. Не понятно по какому принципу вообще Exchanger наследуется от Parser, это два семантически друг с другом не связанных класса. И почему у Exchanger есть метод getPage тоже не ясно. Можно пойти по другому. Сделать отдельный класс Loader с методом load и оба унаследовать от него. Это в целом тоже задачу решает, но если появится еще специфичная функциональность которую могут использовать оба наших класса? Множественного наследования нет. Добавлять эту функциональность в Loader? Опять же нарушится консистентность нашего Loader. Можно пойти третим путем. Сделать интерфейс Loader и указать что Parser и Exchanger требуют в качестве зависимости что-то, что имеет метод load. В этом случае нет проблем описанных выше, и есть доп. плюшки, например упрощается тестирование, потому что можно будет вместо обьекта который реально лезет куда-то по http передать заглушку которая просто в методе load возвращает готовые данные.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы