Pull to refresh

Comments 132

сейчас придут быдло кодеры и скажут, что интерфейсы - бесполезнео зло, да и вообще веб для ооп - не место, городить классы - признак помешанности, и вообще проще написать одну большую функцию, котоорая будет делать все.
зачем так бояться быдлокодеров?
пусть скажут ^_^
чем Интерфейсы заменяют Абстрактные классы в PHP?
Хотя бы тем, что это две разные чтуки по сути. И хотя бы тем, что один класс может имплементировать несколько интерфейсов, а наследовать может только один абстрактный класс
а смысл в этом для PHP какой-то есть?
я например не совсем понимаю реальное использование интерфейсов в PHP,
кроме как красивой фишки ООП.
UFO just landed and posted this here
А смысл в этом какой-то есть. К примеру упрощение жизни девелоперам.
Интерфейс по сути - это абстрактный класс, содержащий только абстрактные методы. Еще можно от нескольких интерфейсов "наследовать"
Использую, но они сильно тормозят приложения
А есть какие-нибудь цифры (хотя бы примерные)?
Не записывал :) Просто замерьте время с implementом и без него. У меня разница была около 20 раз для пустого класса (не могу понять даже почему)
неправду говорите, особено в слове сильно. ибо интерфейсы — это в основном проверки на этапе компиляции и редко на этапе исполнения. Нельзя ж так обманывать
Это основано на моих тестах, может они и не обьективны, но моё мнение изменить могут :)
покажите ваш тест. Аксерелератор так вообще сведет в 0 доп накладные расходы на которые на этапе сборки.
всегда мечтал хранить всё, что пробовал тестировать 3 месяца назад…
он делался для себя, а значит сделал вывод — удалил…
Да, в целом так.
Но есть нюансы, например A implements B — при использовании xcache B все равно будет подгружен через __autoload()

Хотя на самом деле на этапе выполнения опкода виртуальной машиной интерфейсы уже не нужны.
В том то и дело. Мне вообще не понятны эти утверждения насчет скоростей. Боюсь, что если копать, то окажется что это не аргумент основной, а основной другой.

как показывает опыт интерфейсы незаменимы при стандартизации интерфейсов. Таким образом вы готовите почву для рефакторинга и проведя его вы как правило получите выигрыш в скорости намного больший чем экономя на них. я не говорю даже о устойчивости кода, о наглядности (засчет выделения абстракций), о скорости нахождения лог.ошибок.
Подписываюсь под каждым словом
на этапе выполнения опкода виртуальной машиной интерфейсы уже не нужны.

нужны, пример:
intarface B…
if ($obj instanceof B){} — заранее не известно что будет жить в $obj
поэтому я и писал
это в основном проверки на этапе компиляции и редко на этапе исполнения.
Теоретически для каждого класса можно хранить массив всех его типов, этот массив четко известен на этапе создания опкода.

То есть для obj мы знаем основной класс, дальше можем запросить этот массив.

Если один из заявленных интерфейсов не реализован — об этом тоже четко известно на этапе создания опкода.

То есть в теории интерфейсы все-таки не нужны на этапе выполнения.

Конкретная практическая реализация — это конечно немного другое…
да, вы правы, в таблице наследования класса все есть, учитывая что на нее ссылается каждый экземпляр, то действительно на этапе исполнения нет наклодных расходов вовсе. Что-то я протормозил. Спасибо.
да, вы правы, в таблице наследования класса все есть, учитывая что на нее ссылается каждый экземпляр, то действительно на этапе исполнения нет наклодных расходов вовсе. Что-то я протормозил. Спасибо.
а теперь давайте вспомним где в пхп у нас идет компиляция…
Все-таки в общих чертах вы оказались правы :)
По-моему одно из самых важных нововведений PHP5
Чем оно важно? если можно, на примере. Честно, стараюсь понять, и не могу.
А как же! Ждали.. ждали.. и не использовать? :)
ага, согласен, вот только результаты пока 50/50
И еще топик минусуют :(
на мой взгляд, потому как, это пока только для красоты ООП. Интерфейсы в PHP ничего такого особенного не добавляют.
в Java, C# - интерфейсы реально выполняют свою роль.
а в PHP, возможно к 6 версии начнут
UFO just landed and posted this here
Без всей то строгости в типизации, они конечно не играют настолько важную роль, как играли бы в Яве, но их наличие по сути позитив. Не приходится придумывать всякие Mixin или протоколы...
Насколько я знаю, за пример при разработке и бралась Ява.
А вообще в php 6 много фишек для ООПа сделают.
Да, использую.
Начал использовать PHP (да и вообще, программировать) сразу с пятой версии. Интерфейсы - мегаполезная штука, не представляю, как раньше люди без них жили =) Хотя, вообще, можно эмулировать..
даже когда не хочу использовать, не получается :) поэтому использую всегда
Покажите же уже пример, который показывает, как интерфейсы жить помогают…
А насчёт быдлокодеров, то они теперь наоборот стараются всё настолько заобъектить, что в итоге эту кашу переварить становится просто невозможно ;)
Поддерживаю, покажите (или расскажите) ... я кроме имплементации SPL-интерфейсов не нашел пока ни одного удобного (оправданного) применения, как ни старался
например вы очень облегчите жизнь использующим ваши классы разработчикам, если на видном месте опишете интерфейс с некоторыми комментариями...
т.е. я вижу пользу интерфейсов:
  • собственно в создании интерфейсов между объектами

  • в самодокументировании и самоконтроле

  • в spl-интерфейсах, таки повторюсь
Абсолютно согласен с вами, но в реалиях жизни времени на самодокуметирование - нет.
А жизнь облегчить можно так же и докой (даже результат работы phpDocumentor'а может оказаться юзабельнее интерфейсов на видном месте)
простите, но чуш сказали полную. В реально жизни нет времени писать Доки, но есть время писать самодокументируемый код.
Качаем Zend Framework, ищем по слову interface, фтыкаем.
Вы как бы говорите нам о том, что сами не в теме.
Зря вы так. У Zend Framework действительно стоит многому поучиться, в том числе и применению ООП на деле.
Интерфейсы там применены к месту.
Подписываюсь под каждым словом
Скачал я ZF/ Вы считаете if ($object instanceof IInterface) { - применением интерфейсов к месту? Ээ...
Посмотрите цепочки фильтров и валидаторов например
(Zend_Filter и Zend_Validate). Фильтры и валидаторы реализуют интерфейсы (implements), оставляя возможность наследования.

/**
* Adds a filter to the end of the chain
*
* @param Zend_Filter_Interface $filter
* @return Zend_Filter Provides a fluent interface
*/
public function addFilter(Zend_Filter_Interface $filter)
{
$this->_filters[] = $filter;
return $this;
}

Это первое, что пришло в голову, на самом деле там есть более удачные примеры.
Мне ничего не мешает написать так, и я нисколько не обломаюсь:

public function addFilter($filter)
{
$this->_filters[] = $filter;
return $this;
}
В больших сложных проектах с несколькими программистами такой код - зло (или детство:).
Почему? Вы сейчас фактически говорите, что все языки без типизации - зло, или что все объекты должны ОБЯЗАНЫ реализовывать интерфейсы.
Ну ведь мы сейчас только про PHP говорим.
Если метод объявлен с type hinting - одного взгляда на него достаточно, чтобы понять, что он примерно делает.

Хороший код сам ведет программиста, не давая ошибиться.
Я так понимаю что вы за строгую типизацию в PHP? Мне кажется что проектная документация - гораздо лучшее решение проблемы (нежели интерфейсы) для проектов с большим количеством участников. Я исхожу из собственного опыта.
Да, я за максимально строгую типизацию и строгость кода.
Типизация не мешает проектной документации, и то и другое - хорошо.
Тогда наш с вами спор выходит за рамки обсуждения интерфейсов в php. Это уже будет "Строгая типизация: за и против".

У меня вопрос, почему тогда вы работаете с PHP, а не скажем, с Java?
Да, у меня есть желание проститься навсегда с PHP, я уже начал разрабатывать свой web-фреймворк на C++. Но есть два больших проекта, которые нужно сделать быстро, поэтому пока использую PHP.

Вообще я нахожу PHP5 неплохим языком, если конечно использовать его правильно.
Понятно, меня то как раз и прельщает отсутвие типизации в PHP, поэтому с удовольствием пересел на него с C++ и Object Pascal. :)
Прямо сразу и с плюсов и Object Pascal? ;)
Не дописал. С позиции строгой типизации, я с вами полностью согласен. Для этого интерфейсы очень удобны. Но это не технологическое их использование, а организационное. А я пытаюсь найти разумное технологическое использование. Его как раз в PHP то и нет. И как раз в ввиду отсутсвия ОБЯЗАТЕЛЬНОЙ строгой типизации.
Да, возможно это больше организационная штука. Возможно это скорее для программиста, чем для программы. Но без таких вещей в крупных проектах не так комфортно. Лучший код рождается там, где комфортно программисту.

А по поводу отсутствия ОБЯЗАТЕЛЬНОЙ типизации - вам ничто не мешает сказать "в моей программе типизация ОБЯЗАТЕЛЬНА" и писать максимально строгий код.

Кстати, тайпхинтинг в параметрах функции обеспечивает автокомплишн с выводом встроенной документации (например в Zend_Studio), что в больших проектах с сотнями классов и тысячами методов очень сильно помогает.
Мы используем PHPEd, он выводит нашу проектную документацию. с типами и кратким описанием параметров. Мухи отделены от котлет и программисты счастливы и им комфортно.
я имею в виду вот что:
function foo(Bar $bar) {
$bar->ТУТ_ВЫСКАКИВАЕТ_СПИСОК_МЕТОДОВ_КЛАССА_Bar_C_ДОКУМЕНТАЦИЕЙ

function foo($bar) {
$bar->НИЧЕГО_НЕ_ВЫСКАКИВАЕТ(откуда IDE знает, что такое $bar)

вот...
Это бесспорный плюс в сторону типизации. :)
Конечно, попробуйте запомнить тысячи классов и методов
Зато обломается и будет громко матерится человек которым этим кодом воспользуется.
Тебе все еще не дает покоя этот коммент? Бедненький
Интерфейсы раскрутились на полную в COM-архитектурах, когда есть библиотека черный-ящик, которая содержит в себе объекты, доступ к которым осуществляется через интерфейсы этих объектов. И если вы считаете что основная суть интерфейсов в instanceof то преречитайте этот коммент еще раз и изучите историю предмета.
Без строгой типизации и дефолтного error_reporting(E_ALL) смысла в их использовании нет.
потому что method_exists можно и без интерфеса сделать. соотвественно штуки типа ($object as IFoo).bar($foo) нафиг не нужны. Про добавления свойств я вообще говорить не буду. Интерфейсы удобны для языков со строгой типизацией. В языках со скалярными переменными в них нет необходимости.
Интерефейс это один из результатов проектирования, проектирование это основаная часть программирования. Интерфэйсы делают код более прозрачным, логичным и понятным, и являютса правилами и направлением для логики. Есле вы пишите маленькие "скриптики" или даже "классики" то скорее всего вам они необъязательны. Но есле вдруг вы взялись за огромную работу которая требует гибкости кода, его возможной разширяемости и масштабируемости то интерфэйсы это то что вам скорее всего требуетса знать.

Самый распространённый пример применения интерфэйса это абстракция базы данных. Давайте представим для чего...?! В PHP есть полно расширений для работы с базами данных, для MySQL их не менее трех msql, msqli, pdo_msql и т.д. А ведь по сути нам всего нужно выбрать, обновить, вставить, удалить... что собственно говоря и являетса базовым интерфэйсом. Мы отделяем то что нам необходимо от того как это реализовано. Нам не надо знать как это реализовано мы знаем как это работает, а сама реализация может менятса десятки раз.

Советую почитать книжку PHP 5 Power Programming там очень просто и понятно всё написано.

http://www.informit.com/content/images/013147149X/downloads/013147149X_book.pdf
Для этого не интерфейс нужен, а базовый абстрактный класс. Интерфейсы нужны для того что я выше в комменте написал.
Хорошо, допустим такой пример. Абстрагируем кеш. В данной ситуации от вашего абстрактного класса ни останется ни единого конкретного метода, одни абстрактные. В принципе это всё равно можно сделать абстрактным классом, но тогда теряется возможность наследовать в классе-реализаторе ещё какой-то класс.
Почему все путают интерфейсы с наследованием? Интерфейс нам говорит, что мы обязаны реализовать в классе все методы. Это как памятка. Типа: "Программер, не забудь реализовать это, это и это, иначе случится что-то плохое." Так что интерфейсы не дают нам возможности наследоваться от еще какого-то класса. И в итоге в ракурсе PHP вообще нам ничего не дают.
А почему мы не можем наследоваца от какого-нибудь класса и выполнить все требования интерфейса?
Действительно. Себе этот вопрос задай. Если ты думаешь, что выше сказаное - это аргумент, то е***сь в рот. Твой Удафф ;)
Ну так. Допустим мы реализуем кеш через Memcache. Класс-аксессор при этом принимает в конструкторе параметр типа CacheSorage.
Тогда мы создаём свой класс так:
class MemCacheStorage extends Memcache implemens CacheStorage.

Вы правы — интерфейсы не дают ничего нового, всё что они могут — ограничить нас в количестве ошибок, не более того.
Интерфэйсы и Абстрактные классы в PHP похожи, но это не одно и тоже. Какже например instanceof ??? И вообще абстрактные классы пойдее могут определять тело методов(в PHP немогут) а интерфэйсы нет.
А где я сказал, что это одно и тоже? Я утверждаю, что интерфейсы в PHP - бестолковая вещь. Вот и все.
Есть очень интересные и полезные применения интерфейсам.
Оторвитесь от книжек, определений и прочей теории. Абстрагируйтесь и поразмыслите головой какая польза от этих самых интерфейсов в PHP?
А какая польза от комментариев? Тоже, непосредственно, на исполнение программы особенно не влияют.
Вот я и говорю, что кроме SPL, реального применения почти нет
знаешь, код можно и в столбик писать. И, я тебя даже удивлю, - он будет работать быстрее чем четко струткурированный по абстракциям и слоям объектный монстр. Но вот потребуется тебе что-то с ним сделать, ты жопу порвешь и будешь мечатать, что вот копипаст, который сделал ты сейчас - ты правильно подправил и ты не словишь еще с десяток ошибок.
Вы свою манеру изложения, ака "я самый умный" оставьте пожалуйста при себе.
Без вас знаю где и зачем используются интерфейсы, и как они "упрощают" сопровождение кода.
Бьюсь об заклад, что там, где вы их используете, у вас постоянно выскакивает "instanceof". Так? А о чем это говорит? А об этом читайте в книжках Мартина Фаулера
Это говорит о том, что вам все таки следует пойти и ударица об заклад :)
Польза хотябы в том чтобы научить PHP програмистов лучше мыслить в ООП а это значит на всех совремменных языках програмирования. Раскажи лучше какой вред?
в js и питоне нет интерфейсов :)
в асме классов нет, хороший язык получился. Может быть они ваще ненужны7
асм язык низкого уровня.
А питон высокого.
Он стоит на том же уровне, что и Java и вполне конкурентноспособен по отношению к ней, хотя и ООП у него не совсем такое в деталях.
Javscript это прежде всего СКРИПТ язык, да мощный скрипт язык, да с потдержкой ООП а точнее там всё что ты создаёш обьект, но он нетребует потдержки ООП такого уровня, во всяком случае раньше не требовал. В Pythone родной потдержки интерфэйсов нету, аля кейворда interface зато это не мешает их реализовывать в виде классов посмотри хотябы на интерфэйсы Zope.
Если интерфейсов не существует их изобретают. В питоне изобрели протоколы. Имхо, всё-таки немного более громоздкое решение, чем интерефейсы. Да и просто интерфейсы как-то привычнее.
Вред от наличия интерфесов в PHP есть - ими пользуются и делают это неправильно, лишь усложняя сопровождение
О боже... ну давай тогда ещё приведём пример програмистов которые пичкают свои классы различными методами и считают что это ООП... может тогда вообще ООП в PHP поставить под сомнение и нивкоем случае не использовать потому что многие делают это неправельно?
Для PHP — расширенный тайпхинтинг. И это неплохо, заметьте.
Применяю ООП, интерфейсы не использую. Насколько я понимаю, интерфейсы помогают:
1) более тщательно следить за полиморфизмом (все полиморфные классы реализуют один и тот же интерфейс)
2) "документировать" предназначение класса (типа он наследует iPrintable, значит, оно может печатать)
3) наверняка я еще десяток пунктов не знаю.

Вообще, полагаю, интерфейсы бесполезны, когда они идут в комплекте с единственным классом. То есть интерфейс может быть полезен только тогда, когда описывается взаимодействие классов или их взаимное "положение" в системе.

Будьте добры, подскажите пожалуйста действительно удобное и полезное применение интерфейсов в РНР.
Повторю свой пример с кешем. Есть управляющая функция, которая принимает объекты, реализующие интерфейс Cacheable. Такими являются MemCacheStorage, ApcCacheStorage, FileCacheStorage, DbCacheStorage.
Какой из них будет применён решает юзер в конфиге, функции в принципе пофиг, но ровно до момента когда нужный класс не инициализировался или кто-то попробовал подать на вход чужеродный класс. Тут-то и выпадет ошибка.
Млин, извиняюсь, попутал. Интерфейс назывался CacheStorage. Сacheable — интерфейс для кешируемых объектов.
Иначе говоря, это п.1: помощь в реализации полиморфизма, верно?
Да, если я правильно вас понял. Следить в данной ситуации это очень абстрактное понятие. Уточню для данной ситуации: один разработчик следит за собой и другими на этапе выполнения скрипта. Раньше увидеть ошибку в данной ситуации проблемотично.
Вы же знаете, наверное, что такое Type Hinting?
*«проблематично», извиняюсь
>Вы же знаете, наверное, что такое Type Hinting?
нет. *стыдно* Пошел изучать тему.
А, блин. Это всего лишь указание типа объекта, передаваемого в параметрах функции? :)
Знаете-знаете, я думаю, просто название такое не слышали. =)
В любом языке вы пишите список аргументов и указываете их типы «void a(String a)», типа такого. Если какой-то из типов при вызове функции не совпал, то выпадает ошибка, либо компилятора, либо интерпретатора.
PHP же к типам так не придирается, ему число в строку преобразовать — раз плюнуть, поэтому в PHP убрали элементарные типы в качестве ограничений для параметров — если что, мол, типы к нужным сами приведём.
Поэтому такой код:
function a(string $x){}

в PHP неверен.

То что оставили нам это возможность указывать свои собственные типы в качестве желаемых, да ещё array, кажется и называется это всё дело «Type Hinting», т.е. возможность «подсказать тип».
Кстати, с помощью одного костыля можно реализовать и ограничения на простые типы, но я это у себя убрал вскоре, так как процентов на 5% скорость работы уменьшалась.
Вам же уже сказали, что эту же задачу можно также решить при помощи абстрактного класса
Конечно можно, к примеру в том же си вообще нет интерфейсов, а их роль выполняют абстрактные классы. Но в си есть множественное наслодовение...
но в приведенном примере множественное наследование не требуется
Требуется. К примеру класс DbCacheStorage наследуюется от класса DB, который хранит несколько нужных утилитарных функций и сам наследуется от PDO.
Оспорю, DbCacheStorage должен наследоваться от AbstractCacheStorage и инкапсулировать DB

логически: хранилище кэша это не расширенное новыми методами подключение к СУБД
Я в принципе согласен с вами, но где-то в глубине души я разделяю внешние стандарты, которые надо блюсти строго и внутренние, которые можно подогнать под своё удобство и в данной ситуации поддаюсь искушению наследоваться от Memcache, PDO, etc. потому, что это удобно.
Это какие такие стандарты?

присмотритесь к структуре: ваш DbCacheStorage органичен использованием лишь одного конкретного типа СУБД. Тоже самое про наследование от PDO.

Если уж DB, то AbstractDB и набор потомков для каждого типа DB.
Если уж CacheStorage, то AbstractCacheStorage и набор потомков для разных типов хранилищь
Если уж DBCacheStorage, то параметризованный AbstractDB (т.е. умеющий работать с любой DB)
DB итак абстрактным является;
CacheStorage тем более интерфейс;
DBCacheStorage суть обвеска DB новыми функциями;
конструктор DB в качестве аргумента кушает тип DB, так что он с любой базой работает по умолчанию;
а не получается ли у вас 2 подключения к DB? одно от CacheStorage, а второе от основного DB, используемого в приложении?
он не выносной, он родительский, он же соединение и держит
тогда непонятно зачем вам вообще интерфейс DbCacheStorage, если фактически применить другой объект (например ApcCacheStorage), реализующий этот интерфейс нельзя ибо тогда приложение останется без коннекта к СУБД
скоро вы меня запутаете окончательно)
ещё раз:
interface CacheStorage
class DbCacheStorage extends DB implements CacheStorage
class MemCacheStorage extends Memcache implements CacheStorage

про коннект к ДБ поясню — на данный момент используется SQLite, так что коннектов и правда много, но все они к разным БД.
ну вот я и говорю - структура рабочая, но непереносимая. Т.е. реального применения интерфейсов и наследования - нет.
Резюмируя:
В комментариях налицо недопонимание между людьми. Те, кто говорит об отсутствии необходимости пользоваться интерфейсами (в том числе я), говорят не о интерфейсах, как часть парадигмы ООП, а скорее о ключевых словах "implements" и "interface" в PHP5.

Интерфейс, как структурная составляющаяя, есть у любого класса, как неотъемлемая его часть.

Быть может имеет место утверждение: Интерфейсами пользуются все, но не все об этом догадываются?
*снимая маску серьёзности*
Если не секрет, почему вас так тянет на абстрактные классы? =)
Я бы сформулировал так:
Меня не тянет к ключевому слову interface.

А вдруг я затра обнаружу у всех своих "реализаторов" интерфейса IPrintable, один и тотже метод "::print()" - мне станет жутко неуютно
упс. Думал об одном, а написал другое:
В общем я перестраховываюсь на случай рефакторинга "поднятие метода"
Я так и понял. Что ж, спасибо за разъяснение. Приеду домой и буду долго думать. =)
Опять же, вопрос проектирования, т.е. мы его тут до завтра можем обсуждать.
И всё же, будь в PHP множественное наследование, вопрос про интерфейсы бы так не стоял.
Так как примера я не увидел — то наведу его сам. Вот собственно он.
И вопрос не к месту. Интерфейс нужно использовать там где нужно. Не только в PHP.


>>> import this
The Zen of Python, by Tim Peters
...
There should be one — and preferably only one — obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
...
Спасибо. Если только в SPL, то должно хватить для применение.
SPL - классический пример. позволяет вашим объектам обрабатываться встроеным функционалом PHP. Это COM.
Думаю что каждый уважающий себя и окружающих программист должен использовать interface для того чтобы доставить себе и другим удовольствие кодинга. Понятное дело что это не просто и можно итка без интерфейсов наклепать, но если вы пишите серьезный проект с которым будут работать другие программисты, то им не придется вникать 2 года на изучение того когда что вы написали, я образно, а качественно продолжить работу. Это как пример. А так самому должно быть приятно смотреть на свой прозрачный код. Да и считаю что код хорош и прозрачен тогда когда без доки понятно что и как ИМХО , ну это высший пилотаж )))
Sign up to leave a comment.

Articles