![]() |
Понять интерфейсы
В очередной раз возвращаюсь к этой теме и пытаюсь найти плюсы для себя, как человека, в единственном лице работающим над к.-л. проектом.сКажите пожалуйста, есть ли смысл? Если есть - какие плюсы? Мое понимание ситуации на данный момент сводится лишь к тому что мне более чем достаточно будет наследование (extends), а интерфесы (interface) - лишние куски кода, которые в моем случае не нужны (т.к. над проектом работаю один).
И еще. Допустим так сложилось, что я стал работать в команде - тут мне они понадобятся в том случае если я хочу чтоб другие разработчики знали какой функционал я хочу использовать в том или ином классе, пока я его еще не реализовал. В таких случаях на сколько часто и густо нужно использовать интерфейсы? Все выше написанное мне кажется какой-то фигней, бредом, т.к. структуры проектов не должны отличаться в зависимости от количества разработчиков. В общем надеюсь на помощь. Интересует как часто? когда? в каких ситуациях? какие при этом я получаю преимущества? (не зависимо от количества разработчиков:) ) В общем буду благодарен за любые советы и мысли на тему интерфейсов. Спасибо. ==================== Upd. еще раз спасибо всем откликнувшимся. Думаю у меня еще будет повод отписаться :) |
Представьте ситуацию, у вас есть n-е количество классов у которых нет общего предка, но у всех есть некий набор одинаковых методов и их надо обрабатывать. Тут уже просто наследованием не обойтись. Логичнее описать методы в интерфейсе и работать с объектами как с интерфейсом. Примеры IItemRenderer, IDataRenderer.
|
Использование или неиспользование интерфейсных классов это всего лишь проектировочный ход.
http://ru.wikipedia.org/wiki/Обращение_контроля Чтобы разобраться в этом вопросе, рекомендую прочитать книжек, например, "Рефакторинг" (Мартин Фаулер). |
у многих языков нету множественного наследования классов, а множественное наследование интерфейсов - есть. Поэтому это просто иногда удобно.
Что касается флеша -- интерфейсы можно выбросить, а типизацию переменных убрать, и все будет работать, но иногда удобней их иметь. Это -- раз. два -- если проект компилится несколькими частями, то бывает удобно переменные обьявлять классом только в базовой флешке, а в остальных -- только интерфейсами, а прореализацию компилятор, компилируя флешку, может ничего не знать. три -- при помощи is можно проверять принадлежность переменной интерфейсу. типа if (clicketObj is ITransparentButton)clicketObj.alpha =1 if (clicketObj is IToolTip) clicketObj.showToolTip("Ахтунг!") Часто так делать удобней, чем заводить внутри класса соответствующие флажки. |
Цитата:
|
То, о чем говорит chabapok в пункте 3 - называется еще Маркерами, или маркерными интерфейсами. Они могут вообще ничего не содержать == не требовать от классов реализации каких-то методов. Их смысл - просто дать понять другим классам, что с этими можно что-то делать (пример - IBitmapDrawable, который имплементят все ДисплейОбжекты). Допустим у Вас 15 наследников Спрайта, и Вы хотите разрешить только 4 из них растягивать по горизонтали, а остальные - нет. Помечаете четыре маркером - implements IHScalable, и перед попыткой растянуть такой спрайт спрашиваете, можно ли? Можно конечно завести булево свойство, но - незадача - Вам придется заводить его во всех 15-и классах, и во всех иметь это странное непрактичное свойство, к тому же вылезающее при автокомплите. Хороший пример - тот самый IBitmapDrawable. Представьте, что адобовцам пришлось бы во все(!) классы добавлять такой флаг - может или нет экземпляр быть отрисован в битмап. А тут просто пометили маркером один супер-класс и вуаля.
|
alatar, как я понимаю в приведенном примере как раз наследование подходит лучше
MrPoma, спасибо за ссылку, читаю про SOLID. chabapok Цитата:
Цитата:
Цитата:
У нас есть массив(корзинка) продуктов: фрукты и овощи. Они могу быть красными, желтыми и зелеными. И мы вместо того чтоб заводить переменные, как подсказывает Wolsh, просто проверяем интерфесы, при этом можем сделать выборку как только овощей, так и красных овощей. BggЯ как раз думаю, что не понимаю смысл интерфейсов, потому и создал тему. Wolsh Цитата:
Цитата:
Из того что понял на данный момент: - полезно при первичном проектировании - использование интерфейсов вместо булевых переменных |
Вобщем (не считая маркеров - это НЕ главное их применение) интерфейсы применяются там где:
- не справляется наследование, - чтобы "сузить" интерфейс (чтобы клиент класса не дергал методов, которых его трогать не просят), - чтобы сделать части системы максимально независимыми Пример, где наследование не справляется: Например есть менеджер подсказок и ему нужно передать объект с полем hintText (безобразное решение для огранизации подсказок, но сейчас не об этом) надо показать подсказку и над классом, унаследованным от SimpleButton и над классом, унаследованным от Sprite, здесь мы не сможем впихнуть функцию: Код AS3:
придется реализовывать этот метод и в MySimpleButton и в MySprite, а чтобы с ними обоими мог работать менеджер (без дурацких проверок на тип и опасного приведения типов) пусть реализуют интерфейс IHintTextable В этом плане очень сильно недостает интерфейса IDisplayObject (хорошо хоть IEventDispatcher сделали), т.е. сейчас у нас есть в проекте 2 gui библиотеки и есть 2 типа кнопок. Одни наследуются от Sprite, другие - от SimpleButton У обоих кнопок единтсвенное значимое отличие от DisplayObject - наличие свойства "enabled" Ну и всё - приплыли. Использовать одни и теже классы работающие с 2-мя кнопками нельзя (вернее можно, но криво) - получается либо: Код AS3:
Код AS3:
Код AS3:
|
))Безусловно маркеры - НЕ главное, скорее даже одиозное применение интерфейсов (впрочем же адобовцы его не чураются). Может быть, их прямое назначение не вызывате у меня вопросов, поэтому заострил внимание на маркерах - автор спрашивал "зачем надо".
Цитата:
Основная задача интерфейсов, кроме собственно гарантии наличия методов - объединение того, что не может наследоваться от одного предка, как в случае с DisplayObject и BitmapData. В нередких случаях, когда есть какой-то контейнер (пакер), в который могут добавляться РАЗНЫЕ объекты (виджеты), имеющие интерфейс - т.е. методы - для работы в этом контейнере, Интерфейсы незаменимы. Многоуровневое меню, где пунктом может быть как кнопка, так и другое меню; статусБар - эта панелька внизу многих приложений, в которой помещается несколько Информеров - координаты мыши, подсказка к инструменту, индикатор прогресса, иконки дополнительных служб. Вы стали бы писать отдельный класс, чтобы все это унаследовать от него? А если таких интерфейсов понадобится пять - создавать цепочку из пяти суперклассов? Прелесть Интерфейсов в том что один Класс может реализовывать их несколько сразу, плюс наследовать. |
Пожалуй, стоит добавить, что при загрузке логики извне (т.е. swf-файла с классами) интерфейсы могут быть полезны. Допустим, имеем игру с 4 режимами. И каждый режим лежит в отдельном swf-файле. Как, спрашивается, управлять этими режимами из главной swf-ки (контейнера)? Ответ - использовать интерфейсы. С их помощью можно сохранить типизацию при работе с, в общем, неизвестным содержимым.
|
Цитата:
|
Ответов много, и они объемные, за что отдельное спасибо, поэтому буду отвечать постепенно (к тому же если никто не ответит - они автоматом в конец дописываются)
expl Цитата:
Цитата:
По поводу тех 2х примеров с интерфейсами (не совсем понимаю их работу): 1) мы создаем переменную, которая по сути является интерфейсом. Мы разве можем добавить на сцену интерфейс, даже с учетом приведения типов? Что вообще получится в результате? Мне почему-то казалось, что мы не можем добавить интерфейс на сцену, а если и можем, то какой в этом смысл, ведь там ничего кроме списка объявленных методов с атрибутами и переменных ничего нет. 2) Тут получается мы сразу добавляем интерфейс, т.е. к нему приводим и все это в каком-то контейнере? Это какой-то хитрый контейнер или это может быть любой спрайт? Такое впечатление, что мне еще рано вникать в нюансы с IDisplayObject, т.к. пока еще с основами не разобрался. Добавлено через 13 минут Wolsh Цитата:
Наверное я что-то упустил. Прежде чем спрашивать дальше... В общем получается (интуитивно догадываюсь), что если мы имплементим какой-то класс, то мы можем не просто сказать какие функции использовать ему, но и предоставить сам функционал, т.е. не просто сказать что там будут такие-то функции, но и там будут какие-то функции, которые работают именно так. Я правильно понял? |
Цитата:
У класса BitmapData есть метод draw(), который принимает как параметр - внимание - не DisplayObject, а именно интерфейс IBitmapDrawable, т.е. И битмапдату И дисплейОбжекты: Код AS1/AS2:
Пример - сейвы в игре. Вам надо описать в этом сейве состояние сотни объектов, четверть которых вообще не является дисплейными, например списки инвентаря, и имеет абсолютно разные параметры для сохранения. Все они должны иметь метод serialize():XML (XML это к примеру, формат тут не важен, но он один для всех). Менеджер сохранений проходится по списку подлежащих сохранению объектов и запрашивает у каждого сериализацию - некий набор данных, описывающий все параметры, необходимые для последующего восстановления текущего состояния этого объекта. Классы - самые разные. Все, что требуется - реализация интерфейса, т.е. наличие метода serialize, возвращающего данные в условленном формате. Ясно понятно, что Вы не будете наследовать сто совершенно РАЗНЫХ классов от одного - у Вас это просто НЕ ПОЛУЧИТСЯ, потому что наследование идет только по цепочке. Но Вы можете задать всем этим классам отдельный тип - интерфейс, гарантирующий наличие у них метода для общения с менеджером сохранений. "Гарантирующий" потому, что Класс не будет скомпилирован, пока в нем не будет метода, требуемого Интерфейсом. |
Прочитал еще раз тему, почитал Мука и еще немного в НЕТе пошарился. Кажись начинаю понимать.
Т.е. использование необходимо - при изначальном проектировании проекта. - я говорил "не забыть", в общем по сути примерно тоже и остается, только все это осуществляется автоматически, т.е. я получаю гарантию корректного и типизированного кода - опять же типизация при передаче параметров функциям - получаем гораздо большую гибкость без нарушения той же типизации - маркеры Я правильно понял? Или еще не дошло? Кстати, на сколько часто и густо необходимо использовать интерфесы, ведь по большому счету можно каждый класс имплементить от к.-л. интерфейса. |
У интерфейсов есть один недостаток - это усложнение ревью/ревизии кода, хотя это касается не только интерфейсов, но и использования в качестве аргументов базовых классов (особенно если они во многом абстрактны)
Тяжело без реальной sequence diagramm понять какой код выполняется. |
На самом деле, насколько я знаю, Flash-девелоперы интерфейсами пользуются довольно редко. Все-таки смысл их раскрывается только в более-менее сложных ООП-проектах, да и традиционное отношение сказывается)) Когда вы пять лет флешерили без интерфейсов, взять и вдруг начать ими пользоваться по полной слегка затруднительно.
Да, TanaTiX, все базовые предназначения Интерфейсов Вы перечислили. Надеюсь, новое понимание Вам когда-нибудь поможет)) Удачи! |
Цитата:
внутри менеджера пришлось бы писать так: Код AS3:
Ну или более сурово: Код AS3:
|
Цитата:
|
:eek:
Можно ссылочку поподробнее, где развенчивается этот миф? Да, там где не справляется наследование - можно применить декоратор, но это касается поведения, а не интерфейса класса (здесь НЕ всмысле "интерфейс" а всмысле "набор публичных методов и полей") А если нам надо расширить интерфейс(опять НЕ всмысле "интерфейс") класса в 2-х независимых веточках наследования - мы используем интерфейс (всмысле public interface ISomeInterface) Как могут эти два понятия не быть связанными? |
expl
Код AS3:
Код AS3:
iNils, а можно поподробней? |
Цитата:
Вам же приводили пример в меню, представим что у вас в меню каждая кнупочка уникальна, она выглядит не так как остальные, у нее анимация своя, но она реализует некий интерфейс, и у нее точно есть 2 метода show() И hide() для работы с кнупочками вам ведь больше и не надо? опять же выше приведен пример с использованием метода serialize()... |
nOobCrafter, я сейчас не столько по интерфейсу спросил и по примерам вроде все понятно. Хотя...
Вот я создаю некий объект button. Как я буду пользоваться его методами, когда у меня есть только названия методов? Мне их придется как-то переопределять? Я понимаю ситуации, когда речь идет о классах, но в указанной конструкции создается не класс, а его экземпляр, можно даже по сути сказать "экземпляр интерфейса". Или это я из контекста выдернул кусок и все с ног на голову перевернул? Смотрел на 8й пост. |
Цитата:
Каким образом интерфейс, не имеющий тела функций может реализовать множественное наследование? |
Цитата:
Потом в коде Вы пишете: button.label = "LOAD"; и компилятор вежливо кивает - "ну label так label, мне то откуда знать". А что потом будет в рантайме, покажет Error Message. Начинающего программиста от продвинутого отличает то, что он никогда не ошибается. Начинающий программист верит в то, что конечно же передаст в этот параметр только то, что нужно. Чаще всего так и есть, ибо в двухстах строках трудно заблудиться))) В этой вере вся сила звездочки. Продвинутый программист не верит никому. Он устанавливает жесткие правила, чтобы ничто не могло пойти "не так". В этом смысл программирования. Не должно быть никаких неопределенностей. Если нельзя определиться с классом, поможет Интерфейс, но жесткую гарантию, что label у button есть, получить необходимо. Интерфейс может гарантировать наличие нужных методов и, если надо - наоборот скрыть ненужные, которые может и есть в Классе, но в данной ситуации не должны быть доступны. |
Вложений: 1
Интерфейс в картинках
Вложение 25333 |
Цитата:
Фактически: var переменная:"Тип данных, который по-любому должен иметь определенный метод, какой он окажется в конце концов - не важно" = "Класс, который имплементит Интерфейс и имеет у себя уже реализованный необходимый метод". |
Отсюда один из постулатов философии ООП. Программируйте в соответствии с интерфейсами, а не с реализацией.
|
На этом видео, показан интересный способ применения интерфейсов.
|
expl,
Цитата:
Добавлено через 6 минут @iNils: Цитата:
Добавлено через 9 минут @Автор: http://www.flasher.ru/forum/showthread.php?t=130250 |
Цитата:
|
Цитата:
|
Цитата:
|
народ, может вопрос не в тему, но все же -
а чем отличается использование интерфейса, скажем от использования статического метода из разных мест, описанного в каком-нть классе? |
Приехали.
|
AlexDesinger, см. 14й пост
|
хм...типо все дело в нетипизированных - типа "универсальных" переменных?
|
Нет, всё дело в инкапсуляции.
|
Цитата:
не все равно не понятно - в чем разница между вызовом статического метода из определенного класса и тем, что я реализую интерфейс такого класса, ну разве что в том, что я обязан переопределить у себя все методы, чтоб не забыть сколько я обязан реализовать что ли? дк помоему это как раз менее удобно, чем вызвать нужный метод, а про остальные и не вспоминать и не загружать класс? |
Класс, реализующий интерфейс какбэ говорит компилятору "у меня точно будут точно вот такие поля/методы, за базар отвечу в компайл тайме". Это вот что такое интерфейс. "Вызвать статический метод" и "гарантировать наличие набора нужных полей/методов у класса" - совершенно разные вещи, что в них общего вообще? %)
|
Интерфейс и статик методы - это как порше и Иосиф Кабзон. Можно одно в другом, а можно по отдельности.
|
| Часовой пояс GMT +4, время: 16:28. |
Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.