Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Помогите разобрать понятие интерфейса (http://www.flasher.ru/forum/showthread.php?t=157498)

Фенёк 06.06.2011 18:11

Помогите разобрать понятие интерфейса
 
Уселся читать книженцию Коллина Мука по AS3. Добрался до темы "Интерфейсы" в которой окончательно заплутал.

Объясните пожалуйста, в чем принципиальная разница между интерфейсом и классом? Что значит класс реализует интерфейс? Почему интерфейс не может быть сам реализован?

i.o. 06.06.2011 18:26

Цитата:

Почему интерфейс не может быть сам реализован?
Потому, что в этом его предназначение.
Цитата:

в чем принципиальная разница между интерфейсом и классом?
интерфейс - абстракция.
класс - реализация.

in4core 06.06.2011 18:31

Ну вот давайте представим такую систему.
Есть у вас в руках 10 ручек, разных производителей, разных паст , все ручки соотв. Для чего нужны все эти ручки ? чтобы писать наверное. Значит они реализуют метод Write. Рассмотрим это на примере

Код AS3:

class Pencil implements IPencil
 
    public function doWrtite():void {
    }
public interface IPencil
    function doWrite():void;
 
Main class
 
var pn1:IPencil = new Pencil(color , mark )
var pn2:Ipencil = new EmptyPancil ( color , mark )

Классы Pencil и EmptyPencil - разные , но реализуют общий интерфейс IPencil имеющий 1 метод всего лишь doWrite()

-De- 06.06.2011 18:37

В интерфейсе указывается, какие параметры функция принимает и что возвращает. Реализации (т.е. что собсно делать с этими параметрами и как получать возвращаемое значение) - в интерфейсе нет.
В AS3 можно имлементить сколько угодно интерфейсов, но наследоваться только от одного класса.
PS: Есть термин "абстрактные функции", это как-раз только такие описания функций, как в интерфейсе. В as3 нет таких функций. В С++ есть такие функции, но нет интерфейсов %)

КорДум 06.06.2011 18:41

Цитата:

PS: Есть термин "абстрактные функции", это как-раз только такие описания функций, как в интерфейсе. В as3 нет таких функций. В С++ есть такие функции, но нет интерфейсов %)
В C# зато есть и то, и то ;)

2автор: понимание, зачем они нужны, придет со временем. Если вы только начали изучать as3, советую не останавливаться и идти дальше. Но в будущем обязательно вернитесь к этой главе.

Фенёк 06.06.2011 18:46

Но ведь интерфейсы могут содержать методы, разве это не будет реализацией?

Wolsh 06.06.2011 18:47

Есть утюг, телевизор, ноутбук и паяльник. Все делают совершенно разные вещи, но у всех один интерфейс "вилка на 220". Он гарантирует, что если у Вас в стене есть розетка на 220, то Вы сможете воспользоваться любым из этих приборов. Если класс А и класс В реализуют интерфейс IC, описывающий метод show(), это гарантирует что у обоих классов есть метод show(), принимающий такие-то типы данных и возвращающий такой-то тип данных. Это значит, что Вы можете использовать в коде экземпляр как класса А, так и класса В в одной и той же ситуации, и ошибки – отсутствия у экземпляра метода show() – не произойдет. Что именно происходит внутри метода – реализация – зависит уже от класса. Например рисовальные инструменты – все они при движении мышки оставляют след на "бумаге". Какой именно, размытый как у кисточки или резкий как у карандаша – это уже конкретная реализация. Важно что мы можем подставить любой инструмент и вызывать у него метод "рисуй" единым для всех образом. Заменяемость и расширяемость, универсальность – основные цели Интерфейсов.

Добавлено через 1 минуту
Интерфейсы НЕ могут содержать методы. Они только описывают сигнатуру.

Фенёк 06.06.2011 18:52

А разве не будет альтернативой вместо интерфейса создать другой класс, который будет расширяться?

i.o. 06.06.2011 19:02

Цитата:

А разве не будет альтернативой вместо интерфейса создать другой класс, который будет расширяться?
Ну попробуйте :)
Вообще, Wolsh хорошо донес суть, как, впрочем, и in4core.

Nemez 06.06.2011 19:07

Интерфейс удобен. А есть ли ситуации, при которых он необходим?

-De- 06.06.2011 19:07

Возможно. Но в AS3 можно унаследоваться только от одного класса. И если реально методы класса, который будете расширять вызываться не будут (будут вызываться только методы наследников, у всех разные, все наследники делают override), то надо таки сделать интерфейс, ибо незачем тягать сигнатуры лишние.

iNils 06.06.2011 19:11

Цитата:

Сообщение от Фенёк (Сообщение 1001635)
А разве не будет альтернативой вместо интерфейса создать другой класс, который будет расширяться?

Можно, но:
1. Не всегда. Попробуйте сделать такой общий класс для Sprite и Bitmap.
2. Зачем, когда для этого есть интерфейс?

Crazy 06.06.2011 19:41

Цитата:

Сообщение от Wolsh (Сообщение 1001631)
Есть утюг, телевизор, ноутбук и паяльник. Все делают совершенно разные вещи, но у всех один интерфейс "вилка на 220". Он гарантирует, что если у Вас в стене есть розетка на 220, то Вы сможете воспользоваться любым из этих приборов.

Это антипример из серии "любая аналогия хромает". Потребление энергии не является назначением этих приборов.

Правильный пример: у нас есть старинный чугунный утюг, электроутюг и сковорода. У нас есть интерфейс ФиговинаДляГлажки. Все три реализуют этот интерфейс, т.е. гладить можно и электроутюгом, и чугунным утюгом, и разогретой сковородой. Делают они это по-разному, но все выполняют один и тот же контракт -- глажку.

goodguy 06.06.2011 20:05

Цитата:

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

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

Crazy 06.06.2011 20:08

Цитата:

Сообщение от goodguy (Сообщение 1001666)
мм.. ну вообще-то не гарантирует.

В скомпилившемся коде -- гарантирует.

olexandr 06.06.2011 21:02

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

goodguy 06.06.2011 21:31

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

Допустим диспатчат 2 разных класса одно событие и при этом оба класса применяют общий интерфейс (допустим ISomeInterface), но есть еще и другие классы, которые тоже диспатчат это событие. Нам же нужно делать что-то только с теми классами, которые применяют этот интерфейс.

Для большей наглядности, допустим есть игра, в которой есть различные виды техники, которую нужно уничтожать.
Все виды транспорта будут, естественно, принадлежать к разным классам (Car, Tank, Aaa и т.д.), но есть у них и одно общее, они все должны взрываться.
Для этого создаем интерфейс, например IBlowable, с методом blow();
И имплементим его во всех классах техники.
Теперь, при попадании бомбы в транспортное средство, мы можем проверить в обработчике события так:
Код AS3:

if (e.target is IBlowable) {
      e.target.blow();
}

В этом случае нам не нужно будет проверять принадлежит ли цель к каждому конкретному виду техники, например так:
Код AS3:

if (e.target is Car || e.target is Tank || e.target is Helicopter) {
      e.target.blow();
}

Кто-то возможно скажет: "но ведь можно же, например, првоерить e.target is DisplayObject"
И результат будет true. Но DisplayObject не имеет метода blow();


Вот, как-то так. Надеюсь не слишком стремное пояснение :D

in4core 06.06.2011 21:44

Да блин опять холивар развели )) в первых постах все пояснили что и зачем :) По факту, можно и штаны через голову надеть. Просто если хотите видеть красивый структурированный код = юзаем интерфейсы , там где это будет логично, а там где суперкласс - там суперклассы. Недавно была тема, я там пояснил = когда интерфейсы , а когда суперклассы.
В двух словах : superClass используем для объектов одного типа и имеющих одинаковые методы, лишь мельком различающиеся ( тут оверрайдим) , интерфейс когда объекты РАЗНЫХ типов ( ваза, чашка, стакан, витрина ) но все они имеют один и тот же метод CRASH!

wvxvw 06.06.2011 21:49

По поводу аналогии с розеткой: В глобальном плане она более правильная, чем аналогия с разными вещами для глажки, т.как интерфейс потому так и называется, что описывает способ общения с внешним миром (между поверхносями или между рельефами, ну как-то так), и не описывает, что он должен делать или для чего предназначен. CLI (Command Line Interface) не имеет конкретного назначения, вернее его назначение не более конкретно, чем назначение более широкого понятия, которое включает в себя CLI (общение с пользователем посредством командой строки)... Более того, это вполне себе правильно (предположим, в идиотской инструкции) сказать по-английски, что an electronic device interfaces with power supply through a socket in the wall (дословно: электроприбор взаимодействует с источником энергии через розетку на стене :)). Говорю я это к тому, что, в первую очередь, когда говорят об интерфейсе, то речь идет именно об интеракции / совместимости, а не о сериализации / категоризации. Второе часто бывает следствием первого, но первое не обязательно приводит ко второму, возможен обратный вариант, когда инструмент задействованный для интеракции приводит к дивергенции а не унификации.
В AS интерфейс выполняет дополнительно и функцию сериализации, потому что так реализован в языке, но это побочный эффект, более того, с некоторыми негативными последствиями, такими, как, например, два объекта, в принципе, предоставляющие одинаковый реальный интерфейс, предположим, у обоих наличиствует свойство graphics: Sprite и Shape, только потому что формально не реализуют один интерфейс, не могут быть переданы параметром в одну и ту же функцию.

EDIT: Вот, кстати, сейчас подумал: заглушка для розетки будет очень хорошим примером использования интерфейса т.как она никоим образом не является электроприбором, но реализует интерфейс розетки-штекера. :)

GBee 06.06.2011 21:58

Пример с ручками, как раз и сбивает с толку, так как может быть выполнен обычным наследованием и перегрузкой метода write.

i.o. 06.06.2011 22:00

Программируйте в соответствии с интерфейсом, а не с реализацией (с)

Crazy 06.06.2011 22:09

Цитата:

Сообщение от wvxvw (Сообщение 1001693)
По поводу аналогии с розеткой: В глобальном плане она более правильная, чем аналогия с разными вещами для глажки, т.как интерфейс потому так и называется, что описывает способ общения с внешним миром (между поверхносями или между рельефами, ну как-то так), и не описывает, что он должен делать или для чего предназначен.

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

Если в интерфейсе Drawable есть метод draw, который в одном объекте рисует на экране, а в другом -- заставляет персонажа вынуть меч из ножен -- это не ООП, это шизофрения. Хотя интерфейс вызова соблюден, сигнатура правильная.

КорДум 06.06.2011 22:10

Цитата:

Сообщение от i.o. (Сообщение 1001698)
Программируйте в соответствии с интерфейсом, а не с реализацией (с)

Макконнелл — Совершенный Код?
Кстати, вот в этой книжке очень даже здорово описано, почему и чего.

ChP 06.06.2011 22:11

В теме отсутствуют слова полиморфизм, паттерн....

Crazy 06.06.2011 22:13

Цитата:

Сообщение от i.o. (Сообщение 1001698)
Программируйте в соответствии с интерфейсом, а не с реализацией (с)

Истинно так. Поскольку при использовании объекта нам важно, какой результат мы получим, а не как оно там внутри реализовано.

Если же рассматривать интерфейс тупо как набор сигнатур -- мы получаем бесполезную хрень. Так, один добрый, лично мне известный гражданин спаял клон ZX-Spectrum, за нехваткой комплектующих использовав идентичные разъемы и для видеовыхода, и для питания. Совместимость по сигнатурам была отличная. Но вот при подаче 220В на видеовход компьютер решил, что это нарушение его контракта и сдох нафиг. :)

Добавлено через 1 минуту
Цитата:

Сообщение от ChP (Сообщение 1001705)
В теме отсутствуют слова полиморфизм, паттерн....

...Liskov substitution principle

wvxvw 06.06.2011 22:53

Crazy: Вот именно что нет :)
Интерфейс, задумывлася именно для того, что значит это слово, и вариант с омонимами как раз таки и есть демонстрация интерфейса. Это и есть прямая его функция - обеспечить совместимость, не зависимо от контекста, слово draw не вызовет ошибки. То, что в каком-то контексте данное слово будет бессмысленным - это уже вне полномочий и обязаностей интерфейса. Непосредственно для этого случая можно найти несколько применений, когда draw нужно не зависимо от значения, обработать одинаково, ну, хотябы спелчекер.
Представте, что мы тестируем какое-то утверждение на истинность. К сожалению, я не знаю точных аналогов в русском языке, но для того, чтобы рассмотреть истино ли утверждение, нам нужно сначала удостоверится, что оно valid, потом, что оно sound, и только потом, мы можем судить о его истинности (это если мы говорим о дедукции). Так вот, по аналогии, интерфейс, это средство позволяющее судить о том, что утверждение valid + sound. Или, правильнее сказать, если мы описываем взаимоотношения между двумя объектами, то интерфейсу достаточна та же мера корректности, которая нужна для того, чтобы сделать вывод о применимости объекта к контексту. Интерфейс не гарантирует полной корректности. Т.е. если вы ожидали, что в электророзетку можно воткнуть исключительно электроприборы, то, очень хорошо, что у вас нет маленьких детей, или вам сильно повезло, и ваши дети не пытались воспользоваться интерфейсом розетки в не предвиденных вами целях.

ЗЫ. Java не единственный православный вариант ООП, есть и другие. Мне, например, ближе CLOS, в котором нет специальных интерфейсов на уровне системы. Вместо этого, слово "интерфейс" используется по прямому назначению, например, интерфейс с базой данных, интерфейс с отладчиком и т.п. - это к реплике о том, что значат интерфейсы в ООП.

i.o. 06.06.2011 22:56

Цитата:

Программируйте в соответствии с интерфейсом, а не с реализацией (с)
Это из GoF :)
Цитата:

Макконнелл — Совершенный Код
не читал еще..

Crazy 06.06.2011 23:07

Цитата:

Сообщение от wvxvw (Сообщение 1001714)
и вариант с омонимами как раз таки и есть демонстрация интерфейса. Это и есть прямая его функция - обеспечить совместимость, не зависимо от контекста, слово draw не вызовет ошибки. То, что в каком-то контексте данное слово будет бессмысленным - это уже вне полномочий и обязаностей интерфейса.

Т.е. описанные мной две реализации Drawable Вы находите нормальными и в своем проекте могли бы так сделать?

wvxvw 06.06.2011 23:12

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

Почему-то вас нисколько не смущает возможность соеденить два массива знаков, или сложить два числа, используя одну и ту же родовую функцию "+". А draw вас да, смущает? Более того, вы используете одну и ту же родовую функцию сравнения практически со всем, что только можно, и находите это вполне естесственным, вы не задумываясь, можете кастовать или проверить тип, используя одну и ту же родовую функцию. (А представте, например, что есть языки, в которых нет родовой функции для определения типа объекта, и наличие функции типа as или is в AS для людей пишущих на этих языках - диковинка).

Crazy 06.06.2011 23:20

Спасибо, у меня более нет к Вам вопросов.

Wolsh 07.06.2011 01:59

Crazy, в ответ на Ваше замечание к моему тексту пример псевдокода:
Код:

class Утюг implements ЯВРозетку220Втыкабельный, ЯОдеждуГладящий
class Паяльник implements ЯВРозетку220Втыкабельный, ЯПроводаПаяющий
class Ноутбук implements ЯВРозетку220Втыкабельный, ЯВИнтернетХодящий
class Мобильник implements ЯВИнтернетХодящий, ЯДрузьямЗвонящий

Понимаете разницу между "втыкабельный" и "гладящий"? Интерфейс не обязан описывать НАЗНАЧЕНИЕ, ибо в ситуации, когда метод ничего не возвращает, описать "назначение" невозможно в принципе. Назначение утюга конечно же не в том, что он втыкается в розетку. Но нет никакого смысла описывать назначение, что "утюг гладит одежду", если неизвестно, как заставить его это делать, как использовать класс в коде. Это и описывает интерфейс – наличие вилки на 220 к примеру, без которой Вы не сможете воспользоваться ЭТИМ утюгом для глажки. И хотя ваши паровые и чугунные утюги тоже гладят, у них именно другой интерфейс для операции нагрева. Они все могут реализовывать Интерфейс ЯОдеждуГладящий, содержащий метод
Код:

гладить(одежда:Одежда):ПоглаженнаяОдежда;
но не могут реализовывать Интерфейс ЯОдеждуГладящий, если метод "гладить" требует уточнения – ведь чтобы погладить рубашку, Вам недостаточно иметь утюг и рубашку. Нужен еще один компонент - источник энергии для нагрева утюга. Если есть розетка, но нет печки, чугунный утюг не сможет погладить рубашку. Метод утюга не сможет отработать с такими входными параметрами – рубашка и розетка. Ему нужны рубашка и печка. Это и есть Интерфейс. И того, что на выходе метод возвращает именно ПоглаженнуюОдежду, должно хватать для точности Назначения. Это уже вопрос архитектуры самих данных – как Вы их спроектируете. Если дальше Вы будете использовать ПоглаженнуюОдежду для извлечения кодов запуска ядерных ракет, то пожалуй да, Интерфейс бессилен. Если же сам класс данных соответствует своему назначению, то вот способ – типизация возвращаемых методами значений. Но если метод ничего не возвращает, я не знаю как контролировать "назначение". Мне невероятно интересно, как Вы вообще себе представляете "интерфейс", или вообще ТипДанных, гарантирующий использование "по назначению" методов без типа возвращаемых данных. Как бы это гарантирование могло выглядеть, псевдокод в студию.

fish_r 07.06.2011 02:40

Цитата:

Сообщение от in4core (Сообщение 1001687)
... По факту, можно и штаны через голову надеть....

Не, а, правда. Пробовал? И что, получилось?! :D

in4core 07.06.2011 03:15

ПОлучился холивар

Crazy 07.06.2011 13:40

Цитата:

Сообщение от Wolsh (Сообщение 1001738)
Интерфейс не обязан описывать НАЗНАЧЕНИЕ, ибо в ситуации, когда метод ничего не возвращает, описать "назначение" невозможно в принципе.

Что может быть приятнее, чем явить чудо.

Код AS3:

/**
 * Вынимание меча из ножен.
 * pre: персонаж имеет меч
 * pre: меч находится в ножнах
 * post: персонаж держит меч в руке
 * invariant: количество предметов персонажа не изменилось
 */

function draw():void;


Psycho Tiger 28.09.2011 23:43

Crazy, банально и на пальцах:
Вам поступило сообщение "Я сплю с твоей подругой".
Вопрос: а что же это значит?

Логика Ваша: ну, если спит, значит просто спит. Без вариантов.
Альтернативная логика: если я кот - то я просто сплю. А если я Вин Дизель - то не просто.


UPD: ох, ёлки, мне прислали ссылку на тему просто почитать, я подумал что актуально. Извиняюсь за некропост :)

razerw 12.09.2013 11:10

Цитата:

Сообщение от goodguy (Сообщение 1001684)
Это скорее не для того, чтобы гарантировать наличие методов, а для того, чтобы абсолютно разные классы принадлежали к одному типу данных.

Допустим диспатчат 2 разных класса одно событие и при этом оба класса применяют общий интерфейс (допустим ISomeInterface), но есть еще и другие классы, которые тоже диспатчат это событие. Нам же нужно делать что-то только с теми классами, которые применяют этот интерфейс.

Для большей наглядности, допустим есть игра, в которой есть различные виды техники, которую нужно уничтожать.
Все виды транспорта будут, естественно, принадлежать к разным классам (Car, Tank, Aaa и т.д.), но есть у них и одно общее, они все должны взрываться.
Для этого создаем интерфейс, например IBlowable, с методом blow();
И имплементим его во всех классах техники.
Теперь, при попадании бомбы в транспортное средство, мы можем проверить в обработчике события так:
Код AS3:

if (e.target is IBlowable) {
      e.target.blow();
}

В этом случае нам не нужно будет проверять принадлежит ли цель к каждому конкретному виду техники, например так:
Код AS3:

if (e.target is Car || e.target is Tank || e.target is Helicopter) {
      e.target.blow();
}

Кто-то возможно скажет: "но ведь можно же, например, првоерить e.target is DisplayObject"
И результат будет true. Но DisplayObject не имеет метода blow();


Вот, как-то так. Надеюсь не слишком стремное пояснение :D

Объясните пожалуйста как тогда вызвать метод blow() конкретно у Car

Wolsh 12.09.2013 11:18

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

razerw 12.09.2013 11:55

Цитата:

Сообщение от Wolsh (Сообщение 1146006)
У Класса Car, то есть статический метод класса? Этот вопрос не имеет отношения к интерфейсам. Интерфейсы не могут описывать статические методы.


нет я не про статический а публичный метод. я не могу понять в каждом из классе Car, Tank, Aaa и т.д есть один и тот же метод blow(); как же он работает? если в классе интерфейса IBlowable есть тоже метод blow().
как имплиментных классах вызывать этот метод ну или отправлять аргументы в него.

KumoKairo 12.09.2013 12:04

Цитата:

как же он работает?
Как раз таки прелесть интерфейсов в том, что никому не известно как работают методы, указанные в интерфейсе. Это черный ящик, мы знаем только что, допустим, метод blow() не принимает входных агрументов и ничего не возвращает.

Цитата:

Объясните пожалуйста как тогда вызвать метод blow() конкретно у Car
Код AS3:

var myLittleCar:Car = new Car();
myLittleCar.blow();
//Или так
var myLittleBlowableObject:IBlowable = new Car(); //С учетом что Car реализует IBlowable
myLittleBlowableObject.blow();


razerw 12.09.2013 12:33

что тогда будет в таком случае.
я отправляю в метод blow() интерфейса IBlowable аргумент.
Но метод blow() имплементирова в классах Car, Tank. какая будет реакция? аргумент придет в оба класса? Car, Tank?


Часовой пояс GMT +4, время: 00:09.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.