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

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

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

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

    Приведу пример на коленке. Хотим, например, написать абстрактную файловую систему. Для начала, определим интерфейс, для ФС:

    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 и может без опаски использовать методы этого интерфейса.
    Ответ написан
    14 комментариев
  • В чем суть интерфейсов в программировании?

    Quber
    @Quber
    PHP Team lead
    @syntax Буду короток. Вы всё правильно понимаете. Вы можете описать интерфейс в классе, однако считается что с интерфейсом удобнее. Плюсы приведены в других комментариях. Однако если нет необходимости, можете не писать интерфейсы, это дело каждого.
    Ответ написан
    Комментировать
  • В чем суть интерфейсов в программировании?

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

    А если посмотреть на открытые фрейморки, типа Zend, то там без интерфейсов вообще никуда.

    В общем, воспринимайте интерфейс как самый эффективный инструмент общения разработчиков в команде.
    Ответ написан
    Комментировать
  • В чем суть интерфейсов в программировании?

    Foror
    @Foror
    Графоман
    Для начала нужно сразу понять, что интерфейс это частный случай класса. Но в Java оно имеет отдельное ключевое слово, а в C++ это просто класс без реализации. Поэтому интерфейс просто задает некий стандарт для работы с кучей разнообразных реализаций.

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

    А если вы делаете игру, то можете создать интерфейс Unit, тем самым задав классам определенное поведение. Например, unit должен обязательно иметь метод atack(), isDead() и т.д.

    А дальше, в цикле делаете проверку всех юнитов:
    loop(...) {
    if (unit.isDead())
    removeFromMap(unit);
    }

    Ну и конечно Unit может быть и просто классом или абстрактным классом, в котором реализованы atack и isDead, а может быть только isDead, потому что attack у каждого типа юнита индивидуально и требует собственной реализации. Т.е. приходим к тому, что интерфейс это также частный случай абстрактного класса.

    Т.е. тут уже вступает в действие полиформизм, т.е. интерфейсы по сути дают полиформизм. Ну, а в Java они еще позволяют делать множественное наследование или другими словами задать классу несколько свойств поведения, например Unit может быть также и Iterable, тем самым можно дать юнитам инвентарь и перебирать элементы в нем.

    И соответсвенно если Unit у вас будет классом или абстрактным классом, то унаследовав Unit в Java, вы просто не сможете дать наследнику еще и Iterable поведение, если Iterable будет тоже классом.

    OrcWarrior implements Unit, Iterable - так можно

    OrcWarrior extends Unit, Iterable - так в Java нельзя, но можно в С++, а Unit и Iterable тогда всегда будут объявляться как class...

    Из-за этого, в Java приветствуется не наследование, а композиция. Т.е. нафига каждый раз реализовывать Unit.isDead, если он стандартный? Поэтому, создается скажем класс UnitAI и делается следующее:

    class OrcWarrior implements Unit, Iterable {
    UnitAI ai;

    UnitAI getAI(){
    return ai;
    }
    }

    class UnitAI {

    boolean isDead() {
    ....
    }
    }

    interface Unit {
    void attack();
    UnitAI getAI();
    }

    Вот это называется композиция, т.е. в OrcWarrior, HumanWarrior вы подмешиваете UnitAI, в котором уже реализовано isDead, и тем самым не нужно каждый раз его реализовывать одним и тем же кодом. В С++ такого можно не делать, там есть поддержка множественного наследование, но оно имеет свои минусы. Впрочем, как и композиция имеет плюсы/минусы.
    Ответ написан
    Комментировать
  • В чем суть интерфейсов в программировании?

    leventov
    @leventov
    ООП#Основные понятия

    Без интерфейса (как концепции) немыслимы три из четырех основных понятий ООП.

    Конкретно в Java интерфейсы как отдельные сущности нужны, потому что нет множественного наследования. В C++ и многих других языках с поддержкой множественного наследования интерфейсов как отдельной сущности нет (чисто виртуальный класс - частный случай обычного абстрактного класса).
    Ответ написан
    Комментировать
  • В чем суть интерфейсов в программировании?

    rEAcT1oNmanT1s
    @rEAcT1oNmanT1s
    Да, это сделано именно для восприятия человеком кода. Легкие программы, где не особо много строк кода, не сильно сложны для восприятия человека, а программы которые имеют тысячи строк кода, уже соответственно нужно разделять на файлы в одних файлах лежат условия "что нужно сделать?", а в других "как это сделать?".

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

    Если программа огромная и вы об это знаете заранее, то её стоит разбить заранее на модули. Зачем или почему? Первая причина это воспринимаемость кода человеком, о котором уже шла речь, а второе будет намного легче найти ошибки в исходном коде, который вы будете писать и они будут.

    P.S. Даже когда пишите что-то или задаете вопросы, можете разделять на блоки текста, как написал я, так воспринимается легче чем то, что написано в куче , не правда ли?
    Ответ написан
    Комментировать
  • В чем суть интерфейсов в программировании?

    ptchol
    @ptchol
    Linux system administrator
    Интерфейс это фактически регламент взаимодействия.
    Класс который реализует интерфейс обязан реализовывать все его методы.
    В интерфейсе вы описываете лишь сигнатуры методов, то есть вы указываете что класс наследник должен уметь делать, но как он будет это делать, тот решает сам.
    Таким образом вы уверенны, что если класс реализует тот или иной интерфейс, все объекты данного класса имеют определенный набор методов.
    ООП - мир абстракций :) Впустите его в себя :) Интерфейсы это еше одна абстракция позволяющая отделить описание от реалзиации.

    "Придумать класс с правильным именем" - так вы не сможете заставить "наследников" реализовывать функционал.

    Интерфейсы располагаются на уровень выше классов, если можно так выразиться. Они неявно "объединяют" классы схожие по каким то общим признаком, и которые обязаны (по логике вашего приложения) реализовывать те или иные методы.

    interface Instruments {
        final static String key = "До мажор";
        public void play();
    }
    class Drum implements Instruments {
        public void play() {
            System.out.println("бум бац бац бум бац бац");
        }
    }
    class Guitar implements Instruments {
        public void play() {
            System.out.println("до ми соль до ре до");
        }
    }


    p.s: программисты дополнят и поправят.
    Ответ написан
    2 комментария
  • В чем суть интерфейсов в программировании?

    @ZzZero
    Я делаю систему контроля яркости.
    Я хочу настраивать яркость всего (гирлянды, люстры, фонарика, экрана телефона).
    В коде выглядит примерно так
    class BrightControl
       public void setDefaultBright(Object obj){
             obj.setBright(10);
       }
    }

    Метод setDefaultBright принимает любой объект. Ведь мне всё равно яркость чего настраивать.
    Мой код используют другие разработчики, я не могу контролировать их.
    Как мне убедиться, что у объекта, который мне пришел в качестве аргумента, есть метод setBright?
    Я пишу интерфейс, и говорю, что метод setDefaultBright принимает только объекты, которые реализуют этот интерфейс.

    Если кроме меня самого никто не будет использовать эту систему контроля яркости. То я просто буду держать у себя в голове, что в метод setDefaultBright можно отправлять только объекты, у которых есть метод setBright, но поддержка кода усложняется, через год и не вспомнишь...
    Ответ написан
    3 комментария
  • Скажите, а шаблон проектирования (для PHP), где фичи для приложения выносятся в отдельные модули - имеет какое-то название?

    firedragon
    @firedragon
    Не джун-мидл-сеньор, а трус-балбес-бывалый.
    В общем случае это плагины

    В случае пхр это обычно hooks или middleware
    Основная мысль в том что приложение имеет жизненный цикл и вы можете добавить в определенную точку свой обработчик.
    Ответ написан
    5 комментариев
  • Скажите, а шаблон проектирования (для PHP), где фичи для приложения выносятся в отдельные модули - имеет какое-то название?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    где фичи для приложения выносятся в отдельные модули

    В вопросе уже овтет :):):)

    Package By Feature

    Вот можете посмотреть на примере PHP-проекта от Удальцова Валентина, хорошая попытка (с привязкой по времени):
    https://www.youtube.com/watch?v=2iPNz3p5Xiw&t=3633s

    как разбить приложение на переиспользуемые модули-фичи

    А вот тут сомнения по моему ответу, тк цель обратная — понизить связанность, тогда как переиспользуемость — повышение ее в некотором роде
    Может быть вы сейчас про DRY? Don't Repeat Yourself?
    Ответ написан
    1 комментарий
  • Скажите, а шаблон проектирования (для PHP), где фичи для приложения выносятся в отдельные модули - имеет какое-то название?

    glaphire
    @glaphire Куратор тега PHP
    PHP developer
    В какой-то мере это Separation of Concerns
    Ответ написан
    Комментировать
  • Не смог найти учебник по DDD с примерами на PHP - такой существует в природе?

    glaphire
    @glaphire Куратор тега PHP
    PHP developer
    Carlos Buenosvinos: Domain Driven Design in PHP
    Я ее читала задолго до Эванса, поэтому не уверенна что она качественная, но лучше чем ничего)
    Ответ написан
    1 комментарий
  • Не смог найти учебник по DDD с примерами на PHP - такой существует в природе?

    vitaly_74
    @vitaly_74
    может быт и нет, смотрите на примеры с java они придельно понятны, и синтаксис похож, во всяком свлучае не долго разобраться.
    Ответ написан
    3 комментария
  • Почему внутри handle() Job доступен Auth::user(), а Request - недоступен?

    Fernus
    @Fernus
    Техник - Механик :)
    И да, я использую 'sync' (для тестирования) - может поэтому Auth::user() доступен?

    Да.

    Вообще, может посоветует кто:

    - Я использую для хранения и передачи некоторых данных - сессии.

    Но внутри Job - Request, а, значит, и сессии - недоступны.

    Переписывать логику без сессий - неохота :D

    Или по любому придется, если я хочу использовать Jobs?


    По-любому.
    Ответ написан
    Комментировать
  • Как в Ubuntu Desktop сделать автозапуск VPN настроенный через GUI?

    @q2digger
    никого не трогаю, починяю примус
    гуглите работу с NetworkManager в командной строке.
    есть nmcli , есть nmtui и nmtui-connect

    edited: example
    https://askubuntu.com/questions/43465/how-to-autom...
    Ответ написан
    Комментировать
  • Как сделать localhost безопасным?

    Lillipup
    @Lillipup
    Allons-y, Алонсо!
    Используй docker
    Ответ написан
    Комментировать
  • Вы можете объяснить, что такое четвертая нормальная форма так, чтобы было понятно?

    @grebenyukov
    В примере по ссылке на википедии - представьте, что у вас есть таблица с ресторанами, таблица с видами пиццы и таблица с районами доставки. Теперь Вам надо заложить в схему БД объекты для указания: а) в каком ресторане какой вид пиццы производят и б) из какого ресторана в какой район можно доставить. В примере рассмотрены 2 варианта - 1) таблица с полями (ид_ресторана, ид_вида_пиццы, ид_района_доставки) и 2) две таблицы, одна с полями (ид_ресторана, ид_вида_пиццы) и вторая с полями (ид_ресторана, ид_района_доставки) - и описано, почему первый вариант не в 4НФ. Суть в том, что при первом варианте реализации в БД возможны случаи, когда какие-то из ресторанов одни виды пицц могут поставлять в определенный районы, а другие виды пицц - не могут. Кроме этого, при добавлении нового вида пиццы, мало создать 1 элемент таблицы в справочнике и 1 элемент в таблице связи, а надо сделать это для всех районов доставки. И далее рассматривается другой случай, когда цена пиццы определяется как функция от ресторана, вида пиццы и района доставки (видимо. в этом примере стоимость доставки включена в стоимость пиццы). Вот для этого случая, из-за наличия функциональной зависимости, таблица с ценами будет иметь альтернативный ключ из трех полей как в примере 1) и этого уже не будет нарушением 4НФ.
    Вы можете не использовать первичные составные ключи. Однако, более-менее сложная система скорее всего будет иметь сущности с составными альтернативными ключами - если такой ключ не сделать, возможны логические дубли, составной альтернативный ключ в виде констрейна или уникального индекса убережет от этого. Например, когда в таблице связи ресторанов и видов пиццы будут 2 или более строки с одинаковым набором значений (ид_ресторана, ид_пиццы).
    Ответ написан
    1 комментарий