Добрый день всем. Может мне кто нибудь на "пальцах" объяснить ЗАЧЕМ, именно зачем нужны интерфейсы. Сейчас объясню что меня вводит в тупик на примере ниже. // это интерфейс PHP: <?php interface FileInterface{ public function readFromFile($path); public function writeToFile($path, $some); }?> // это реализация кода с помощью интерфейса (к коду не придираться я вывожу смысл) PHP: <?php require_once "fileinterface.php"; class Shop implements FileInterface{ public function readFromFile($path){ echo "Считываем из файла и возвращаем строку<br />"; // ну или что то другое можно написать } public function writeToFile($path, $some){ echo "Записываем в файл данные $some<br />"; } }?> Вопрос: смысл в такой реализации ?? Если можно написать БЕЗ интерфейса так PHP: <?php class Shop { public function readFromFile($path){ echo "Считываем из файла и возвращаем строку<br />"; // ну или что то другое можно написать } public function writeToFile($path, $some){ echo "Записываем в файл данные $some<br />"; } }?> Смысл подключения интерфейса , если код выше все сделает тоже самое , я вот в упор не понимаю. Можете мне кто нибудь написать пример(например), где интерфейс действительно нужен и он что то облегчает, решает ?? По мне так , то что я написал БЕЗ интерфейса намного проще, легче и лучше.
Интерфейсы нужны для того, чтоб потом подставлять разные реализации. То есть для полиморфизма. Если его нету, то да, нафиг не сдались. Классический пример, который во всех книжках (из реальной практики приводить - это обычно три страницы описывать задачу): PHP: interface Animal { public function name(): string; public function say(): string; } class Cat implements Animal { public function name(): string { return "кошка";} public function say(): string { return 'мяу';} } class Dog implements Animal { public function name(): string { return "собака";} public function say(): string { return 'гав';} } function animalSay(Animal $animal) { echo $animal->name(), " говорит ", $animal->say(); } animalSay(new Cat()); animalSay(new Dog()); Если в двух словах. Если не в двух, читаем https://www.ozon.ru/product/php-8-obekty-shablony-i-metodiki-programmirovaniya-361612458/ --- Добавлено --- Плюс тут в том, что если я заведу сюда корову, лошадь, и вообще весь зоопарк, то функцию animalSay мне менять не нужно будет.
Все равно не понял PHP: class Cat { public function name(): string { return "кошка";} public function say(): string { return 'мяу';} } PHP: class Dog { public function name(): string { return "собака";} public function say(): string { return 'гав';} } PHP: function animalSay() { Cat::name(), " говорит ", Cat::say(); } Вот, то же самое только меньше код и без интерфейса. И даже если добавить всю возможную скотину сюда, с интерфейсом код будет больше, медленнее и непонятнее. Зачем он нужен чисто технически , какие плюсы дает по сравнению с тем что я написал ?? Прочитал кучу инструкций и примеров, никаких плюсов у интерфейсов не нашел и так и не понял зачем они нужны кроме гемороя и усложнения кода. Что с интерфейсом несколько классов (и меньше их не будет, а будет только больше чем без), что без интерфейса. В примере выше можно сделать классы для каждого животного (что в общем то и правильно) и пиши в них функции про рога, копыта, кто сказал мяю, а кто гав. Каким боком тут интерфейс помогает ??
Ну если ты только статику понимаешь, пиши вообще без ООП. От классов тогда никакой пользы, они типа просто неймспейсов для функций становятся Ещё раз, у меня есть функция animalSay(), которая принимает экземпляр любого класса, вообще любого, который реализует интерфейс Animal. Ей всё равно, передам я ей корову или волка, она будет работать. Твоя функция будет работать только с кошкой, она не универсальная. С моей функцией я могу сделать так: PHP: $animals = [new Cat(), new Dog(), new Cow(), new Tiger() /* и т.д. */]; foreach ($animal as $a) { animalSay($a); } С твоей так нельзя. Причём в реальной программе массив подобный $animals будет заполняться динамически, а не вот так статически, т.е. всё будет зависеть от пользовательского ввода, а функции animalSay по-прежнему по барабану, кого ты ей передал, главное, чтоб интерфейс реализовывал класс. Плюс контроль за типами от пыхи - если передашь что-то не то, он тебя обложит матом. Самое главное - сокращается количество уродливых ифов и свитчей, нужно новое животное - добавил класс, и радуешься. Если прибавить к этому динамические возможности пыхи, типа создания класса из имени в строковой переменной, получается вообще красота. Медленнее - не настолько существенно, чтоб учитывать. Непонятнее - если знаешь пыху, и теорию ООП, то всё очевидно. Прочитай Зандстру про паттерны проектирования, я же здесь не буду всю книгу перепечатывать. Больше на 4 строчки кода - ну я как-нибудь переживу --- Добавлено --- Вообще, у всех приёмов ООП есть такой "недостаток", что трудно придумать примеры на 3 строчки, которые были бы сильно осмысленными. ООП для решения сложных задач создавался. Я помню, нам на первом курсе препод на лекции 4 точки на экран с помощью полиморфизма выводил Т.е. то, что можно сделать в один оператор Write (мы с паскаля начинали)
А объясни пожалуйста вот в этом методе PHP: function animalSay(Animal $animal) { echo $animal->name(), " говорит ", $animal->say(); } он так наследует интерфейс Animal ( Animal $animal ) , ну и принимает переменную ??
Это не метод, а функция (поскольку она не в классе). Она ничего не наследует. Она принимает ссылку на экземпляр класса, который обязан реализовывать интерфейс Animal (в пыхе объекты только по ссылке передаются), после чего, вызывает у него методы name() и say()
Вроде все понятно, но черт голову сломит, классы наследую интерфейсы, последний метод вроде обращается к классам и их методам через интерфейс Ну это я понял. В скобках функции пишется (Animal $animal), меня интересует Animal (т.к $animal в твоем случае это либо new Dog либо new Cat), а вот именно Animal что значит, это типо проверка что экземпляр реализует интерфейс Animal , это так пишется ???
Это синтаксис указания типа для аргумента функции, он уже давно в языке имеется. --- Добавлено --- Если я указываю интерфейс, то будут приниматься экземпляры всех классов, реализующие интерфейс. Если укажу класс, то будут приниматься экземпляры этого класса и его наследников. Сейчас мы ещё можем и скаляры указывать (int, string, bool) --- Добавлено --- Не к классам, к объектам. Нестатические методы вызываются у объектов. Да, тут доля абстрактного мышления нужна. Киты ООП: абстракция, инкапсуляция, наследование и полиморфизм --- Добавлено --- Интерфейсы не наследуются, а реализуются. Это своего рода обязательство реализовать те или иные методы.
Вот, теперь начинает потихоньку быть понятным, что и зачем )) Спс. А все методы в интерфейсе ОБЯЗАТЕЛЬНЫ для исполнения ?? Нельзя например какой то один исполнить, а другой нет ?? И последний вопрос (возможно), я прсто в методах и функциях часто использовал указание скаляров : int или : string : array и так далее, а если указать тип для аргумента функции как в твоем случае Animal (как пример) , и передать туда другой тип, то будет ошибка ?? Т.е. функция принимает ТОЛЬКО этот тип аргументов, с другими будет ошибка ???
Класс, реализующий интерфейс, обязан реализовать все функции интерфейса, если он не абстрактный. Абстрактный может часть не реализовывать, тогда будут обязаны реализовать его наследники (а экземпляры абстрактного класса создавать нельзя). Вызывать можно то, что надо, там где надо, никаких ограничений нету. Да, в этом и смысл. Потому что если ты попробуешь у чегой-то ещё вызвать say() или name(), то уже это приведёт к ошибке. А с указанием типа ошибку может заметить ещё IDE до запуска этого кода. Вообще, пыха с каждой версией всё больше типизации добавляет --- Добавлено --- Так, а если ты про вызов функции, ты получаешь объект, и вызываешь то, что тебе надо. Т.е. если меня не интересует в какой-то конкретной функции название животного, я могу не вызывать name(). Точно так же как и без интерфейса - я же не обязан вызывать постоянно всё, что в класс напихано. Что мне надо, то и вызываю. --- Добавлено --- Я, в принципе, сам противник популярной нынче практики создавать интерфейсы вообще для всего на свете, я их делаю только там, где я на 100% уверен, что собираюсь использовать полиморфизм. А тестирование предпочитаю сразу интеграционное, как-то послушал об этом доклад, и счёл аргументы весомыми.
Т.е PHP: interface Animal { public function name(): string; public function say(): string; } class Cat implements Animal { public function name(): string { return "кошка";} } можно реализовать только name() и ошибки не будет или все таки если наследуешь интерфейс то будь добр реализуй все его функции иначе будет ошибка (Класс, реализующий интерфейс, обязан реализовать все функции интерфейса) если я правильно понимаю.??
Реализовать надо всё. Вызывать можно только то, что надо. Просто я это пояснение дал, потому что в прошлом вопросе ты использовал термин "исполнить". А реализовать надо всё, если реализовать только name, пыха даст ошибку. Ещё раз. Интерфейсы не наследуются, а реализуются. Наследуются только классы. Кстати, поэтому есть буква I в SOLID, Interface Segregation Principle. Т.е. в каждом интерфейсе надо прописывать только те функции, которые будут нужны для конкретной задачи. Класс может реализовывать сколько угодно интерфейсов.
лучше не скажешь! поэтому хрен поймешь, пока жизнь тебя не заставит делать что-то большое. без ООП код превращается в неуправляемую зловонную кучу, которую хочется с каждым новым заданием хочется убить и переписать с нуля. а при должном понимании ООП код может эволюционировать без попаболи.