Форум 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=136131)

proxiServer 10.02.2010 17:18

Множественное наследование
 
Хочу наследоваться от нескольких классов. Бред?

Класс наследуется от MovieClip. А если я хочу еще EventDispatcher добавить, что бы мой объект и клипом был и события свои отправлял?

iflamberg 10.02.2010 17:22

Множественного наследования нет. Но на ваше счастье MovieClip уже наследует EventDispatcher.

udaaff 10.02.2010 17:22

MovieClip и так является EventDispatcher'ом.

proxiServer 10.02.2010 17:28

Спасибо. Не знал. )

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

gloomyBrain 10.02.2010 17:33

Цитата:

Организовывать владение экземплярами этих классов?
Вы, видимо, имели ввиду - композиция? тогда да.

Волгоградец 10.02.2010 18:05

В примере с EventDispatcher можно через реализацию интерфейса IEventDispatcher добиться желаемого.

dimarik 11.02.2010 01:43

Цитата:

Сообщение от proxiServer (Сообщение 885328)
Хочу наследоваться от нескольких классов. Бред?

Здесь - да.

wvxvw 11.02.2010 02:08

Зато в AS3 есть множественное наследование для интерфейсов, вот только имплементить интерфейс прикрученый к классу нельзя :(

proxiServer 11.02.2010 10:39

Цитата:

Сообщение от wvxvw (Сообщение 885503)
Зато в AS3 есть множественное наследование для интерфейсов, вот только имплементить интерфейс прикрученый к классу нельзя :(

Эм, это как? Множественное наследование интерфейсов - это понятно. "имплементить интерфейс прикрученый к классу" - это не очень.

wvxvw 11.02.2010 13:11

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

public class MyPoint extends Shape implements flash.geom.Point {
public function clone():Point { return new MyPoint(this.x, this.y); }
// остальная реализация Point пропущена

Код AS3:

var p:MyPoint = new MyPoint(100, 200);
var p1:MyPoint = new MyPoint(300, 400);
trace(Point.distance(p, p1);

Собстенно говоря это почти то же самое, что и множественное наследование, только реализация не наследуется.

lowka 11.02.2010 22:21

Цитата:

Сообщение от wvxvw (Сообщение 885582)
Класс по-сути состоит из двух частей: интерфейс и реализация. Т.е. в других языках, на сколько я знаю в той же яве можно имплементить другой класс, т.е. пример (псевдокод):

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

wvxvw 12.02.2010 00:25

Ну тогда не помню где, но где-то видел такое :)

expl 12.02.2010 00:37

Цитата:

Ну тогда не помню где, но где-то видел такое
В haXe было, только не для flash9.
Плюс реализовывать надо даже скрытые поля.
Вобщем, пользы маловато.

semenyakinVS 15.01.2011 01:36

Цитата:

Сообщение от wvxvw (Сообщение 885582)
Собстенно говоря это почти то же самое, что и множественное наследование, только реализация не наследуется.

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

f.g.programmer 15.01.2011 10:35

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

JackFromChaos 15.01.2011 15:40

Композиция рулит. Поверьте, множественное наследование это зло, и java и c# не случайно от него отказались.
Вначале это может казаться прикольным... Но потом может привести к страшному бардаку... В общем зачастую компаниях запрещено использовать множественное наследование даже на c++

semenyakinVS 15.01.2011 16:27

Цитата:

Сообщение от JackFromChaos (Сообщение 964824)
Поверьте, множественное наследование это зло, и java и c# не случайно от него отказались.

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

Цитата:

Сообщение от JackFromChaos (Сообщение 964824)
В общем зачастую компаниях запрещено использовать множественное наследование даже на c++

Зря.

Цитата:

Сообщение от JackFromChaos (Сообщение 964824)
Композиция рулит // Вначале это [множественное наследование] может казаться прикольным... Но потом может привести к страшному бардаку...

Композиция в смысле множественного наследования – плохая, как мне кажется, идея. Зачастую возникает ситуация, когда необходим объект не только описывающий два разных интерфейса, но и хранящий два набора свойств, связанных с этими интерфейсам. Использование включения тут возможно, но оно не способно отобразить логику, лежащую в основе подобного решения. Если помимо наследуемых свойств у нас имеются ещё включения, то может возникнуть не меньший бардак, чем при некорректном использовании множественного наследования.

Если судить по такой логике, можно обойтись вообще без наследования, только включая – что иногда приходилось делать в AS1.

JackFromChaos 15.01.2011 17:41

"Это приводит нас ко второму правилу объектно-ориентированного программирование: предпочитайте композицию наследованию классов"(с) Банда четырех.
Вообще почитайте "Приемы объектно ориентированного проектирование - паттерны проектирования". Глава введение, раздел "наследования и композиция".
Хотя, конечно, дело вкуса, и каждый волен поступать так, как ему больше нравится...

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

Psycho Tiger 15.01.2011 19:15

А мне было бы круто просто наследовать от EventDispatcher`а вторым классом, чем реализовывать IEventDispatcher.

Nemez 15.01.2011 19:24

Покажите, пож., пример реализации IEventDispatcher. В хелпе непонятно как-то ((.

i.o. 15.01.2011 19:44

Показываем:
Код AS3:

package  
{
        import flash.events.Event;
        import flash.events.EventDispatcher;
        import flash.events.IEventDispatcher;
 
 
        public class MyIEventDispatcher extends Object implements IEventDispatcher
        {
 
                public function MyIEventDispatcher()
                {
                        _eventDispatcher = new EventDispatcher( this );
                }
 
 
 
                private var _eventDispatcher:EventDispatcher;
 
 
 
                public function dispatchEvent( event:Event ):Boolean
                {
                        return _eventDispatcher.dispatchEvent( event );
                }
 
                public function hasEventListener( type:String ):Boolean
                {
                        return _eventDispatcher.hasEventListener( type );
                }
 
                public function willTrigger( type:String ):Boolean
                {
                        return _eventDispatcher.willTrigger( type );
                }
 
                public function removeEventListener( type:String, listener:Function, useCapture:Boolean=false ):void
                {
                        _eventDispatcher.removeEventListener( type, listener, useCapture );
                }
 
                public function addEventListener( type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false ):void
                {
                        _eventDispatcher.addEventListener( type, listener, useCapture, priority, useWeakReference );
                }
 
        }
 
}


semenyakinVS 15.01.2011 21:37

Цитата:

Сообщение от JackFromChaos (Сообщение 964850)
предпочитайте композицию наследованию классов"(с) Банда четырех.

Кто это сказал? Плохая идея.

Задача: "Человек - наследник безмозглой обезьяны. У него есть мозг".

Реализация в таком вот подходе:
"Человек - оболочка с обезьяной внутри. Плюс у него есть мозг".

Реализация в подходе наследования:
"Человек – следующие звено в развитии обезьяны. У него есть мозг."

По-моему, второе звучит более логично.

Привожу сравнительную характеристику собственного производства.

«Наследование-включение»:
«+»
1. Возможность реализовывать функции-провайдеры в наследнике («Декоратор»). Таким образом мы можем запретить к использованию некоторые методы отца (Тут следует заметить, что то же самое можно реализовать и в подходе наследования, но в таком случаи это будет менее естественно для данного подхода).
2. Можно множественно наследовать там, где множественно наследовать нельзя.

«-»
1. Минус - громоздкий код («Декоратор» всегда громоздок).
2. Уничтожение одного из подходов к построению логики кода. Таким образом мы не сможем никак выделить архитектурой родственность между объектами.

«Наследование-наследование»:
«+»
1. Реализует стандарт С++.
2. Изящно – нет лишнего кода.
3. Минус один уровень вызова через точку.

«-»
1. Сложно представить. При неправильном подходе может вызвать захламлённость структуры.
2. Требует умения думать абстрактно.


Цитата:

Сообщение от JackFromChaos (Сообщение 964850)
Вообще почитайте "Приемы объектно ориентированного проектирование - паттерны проектирования". Глава введение, раздел "наследования и композиция".

Я читал книгу по шаблонам авторства Гамма. Почти все книги по паттернам рассматривают java-подобные подходы к архитектуре, где множественное наследование заменено интерфейсами.

Цитата:

Сообщение от JackFromChaos (Сообщение 964850)
В результате программист зависит не от логики, а от реализации компилятора...

Множественное наследование присуствует в стандарте С++. Любой компилятор под него обязан реализовывать множественное наследование.

Думаю, Страуструп дураком не был.

Psycho Tiger 15.01.2011 21:59

Цитата:

Кто это сказал? Плохая идея.
Я рад что наконец-то Вы пришли и сказали нам, что GoF`ы были не кем-то, кого стоит знать. =)

semenyakinVS 15.01.2011 22:10

А кто это?

Через некоторое время:

Почитал. Ясно... А какова их мотивация?

Psycho Tiger 15.01.2011 22:34

Вы тут описывали нам Декоратор. Так вот он тоже с приставкой GoF.

expl 15.01.2011 23:30

Цитата:

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

А разработчики as3 видимо посмотрели на Java, С#, D, ... и решили что и as3 без множественного наследования обойдется
Считается что оно проблемы создает

JackFromChaos 16.01.2011 00:29

Пример реализации EventDispacher с помощью композиции:
Удалил, потому что пример был выше, просто чет не заметил его...
P.S.
На написание ушло не более 1 минуты... Медленнее чем просто унаследоваться, но не так уже и страшно...


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

Сообщение от semenyakinVS (Сообщение 964918)
Думаю, Страуструп дураком не был.

Страуструп при создании стандарта С++ 2.0 от множественного наследования избавился... Хотя шанс, что этот язык когда нибудь появится в реальности, не так уж и велик...

Dukobpa3 16.01.2011 00:38

Имхо множественное наследование - это геморрой)))

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

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

Добавлено через 1 минуту
И вся ветка кажись завязалась вокруг диспатчера, с ним вообще проблем не вижу, та и примеров накидали кучу уже.

JackFromChaos 16.01.2011 00:41

Цитата:

Сообщение от semenyakinVS (Сообщение 964918)
Я читал книгу по шаблонам авторства Гамма. Почти все книги по паттернам рассматривают java-подобные подходы к архитектуре, где множественное наследование заменено интерфейсами.

Я конечно изеняюсь, но в книжке Гаммы, Хелма, Джонсона и Влиссидеса(все таки из было четвера), все примеры были на с++ и ориентирована она была на с++ прежде всего... но это так, к слову...

i.o. 16.01.2011 01:06

JackFromChaos, зачем писать точно такой же код, если он уже написан в посте номер 21?

JackFromChaos 16.01.2011 01:08

Цитата:

Сообщение от i.o. (Сообщение 964983)
JackFromChaos, зачем писать точно такой же код, если он уже написан в посте номер 21?

Сорри... А слона то я и не заметил:rolleyes:

i.o. 16.01.2011 01:12

у вас существенное упущение - не хватает this'а. Должно быть так:
Код AS3:

_eventDispatcher = new EventDispatcher( this );

если хотите, чтобы target в событиях ссылался куда нужно, а не на _eventDispatcher

JackFromChaos 16.01.2011 01:14

Цитата:

Сообщение от i.o. (Сообщение 964985)
у вас существенное упущение - не хватает this'а. Должно быть так:
Код AS3:

_eventDispatcher = new EventDispatcher( this );

если хотите, чтобы target в событиях ссылался куда нужно, а не на _eventDispatcher

Спасибо, буду знать. Может пригодится... я вообще делал приписку, о том, что не уверен, что все будет правильно, именно о чем то таком подозревал:) Никогда не делал свой EventDispacher, примером просто хотел продемонстрировать принцип композиции, а не реальную задачу... Ну в общем вы поняли;)

i.o. 16.01.2011 02:22

Конечно понял, просто сразу прояснил ситуацию ;)

semenyakinVS 17.01.2011 00:57

Хорошо. Объясняю откуда взялась такая приверженность к множественному наследованию.

Пусть у нас есть большой проект (нам всё равно, какую иерархию он имеет, но он ОЧЕНЬ большой). В определённый момент возникает необходимость сделать графический трасировщик (box2d в тестовом режиме). При этом хочется, чтобы трасировщик оставался в парадигме дисплейных списков (иерархичность тестового отображения, родительские отображения передаются в детей, а главный класс иерархии передаёт всё дерево на сцену).

Выход...

Создаём класс (если бы делал на С++, объявил его виртуальным) с функцией
Код AS3:

graphTrace(parentSprite:Sprite):void

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

Но тут оказывается, что множественного наследования нет! Не выйдет передавать базовый трасировщик как папу-класс. Как папу-интерфейс – можно, но что тогда делать со спрайтом? В интерфейс-то переменные совать нельзя!.. Тащить его по всей структуре, совать в наследников? Засорять private-секцию всех объектов системы?

Ладно, свойство одно, а если их пять? Если десять? Тоже везде заново писать в код наследников?

Ладно, такой класс один!.. А если много?

Например, у нас, в нагрузку ко всему прочему, есть класс, описывающий стандартный объект иерархии. Какой-нибудь CHierarchical? У него есть поле parent. Можно тоже обойтись без класса, но при этом поле снова-таки попадает в наследников… Дурная, надо сказать, наследственность.

Короче, я красивого выхода из подобной ситуации не вижу. Может кто-то подскажет?

Добавлено через 23 минуты
Так. Попробовал реализовать.

Не учёл, что описать вынесенные в наследника свойства надо будет только один раз, потом они будут переходить к наследникам, если описать его как protected. Будет легче, чем думал, но тоже не мёд, если честно.

Но я уже не уверен, что был сто процентов прав...

Добавлено через 1 час 4 минуты
Всё. Переделал... Однако, код мне начинает нравиться, он стал более управляемым!

Но тут как в игре в пинг-понг - повышаешь управляемость, но теряешь в скорости игры. Код стал более громоздким и в нём стали весомее комментарии.

В общем, так как-то:

Код AS1/AS2:

public class Child implements Interface_1, … , Interface_N
        {
                // БЛОК ОПИСАНИЯ НАСЛЕДУЕМЫХ СВОЙСТВ
 
                // эмуляция блока свойств Interface_1
                …
                // эмуляция блока свойств Interface_N
 
                // БЛОК ОПИСАНИЯ СВОЙСТВ И МЕТОДОВ Child
 
                // свойства Child
 
                public function Child(/*ПАРАМЕТРЫ КОНСТРУКТОРА Child */)
                {
                        // ЭМУЛЯЦИЯ КОСТРУКТОРОВ СВОЙСТВ
 
                        // эмуляция конструктора Interface_1
                        …
                        // эмуляция конструктора Interface_N
 
                        // КОНСТРУКТОР Child
 
                        // здесь творятся свойства Child
                }
 
 
                // РЕАЛИЗАЦИЯ МЕТОДОВ Child
                . . .
 
 
                // РЕАЛИЗАЦИЯ МЕТОДОВ Interface_1
                . . .
                // РЕАЛИЗАЦИЯ МЕТОДОВ Interface_N
        }


dimarik 17.01.2011 14:02

Это вы сейчас кому разговариваете слова? Вы поняли зачем нужны интерфейсы?

Psycho Tiger 17.01.2011 14:46

Вот в Вашем примере это решается одним интерфейсом, ITraceable.

semenyakinVS 17.01.2011 15:04

Цитата:

Сообщение от dimarik (Сообщение 965258)
Это вы сейчас кому разговариваете слова? Вы поняли зачем нужны интерфейсы?

Нет. Я понял как очень извращённо можно с помощью них эмулировать множественное наследование.

Те комментарии, которые описаны у меня ДОЛЖНЫ БЫТЬ в коде, они должны предварять код, который описывают. Иначе код станет нечитабельным и вообще ужасным. Использование такого подхода - акт отчаяния.

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


Да и, кстати, описанный подход к формату будет действенным только для первого уровня иерархи. В более сложной ситуации - когда необходимы наследники от не корневых классов - он не поможет. Останется только композиция. (Могу показать картинку, не не понял как её вставлять сюда).

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

Сообщение от Psycho Tiger (Сообщение 965269)
Вот в Вашем примере это решается одним интерфейсом, ITraceable.

Верно. Но вы бы видели код в ситуации, когда надо много наследников. Могу показать, если интересно.

Psycho Tiger 17.01.2011 15:30

Цитата:

Верно. Но вы бы видели код в ситуации, когда надо много наследников. Могу показать, если интересно.
Это проблема не платформы и не языка, а Вашей архитектуры.

dimarik 17.01.2011 15:32

Цитата:

Сообщение от semenyakinVS (Сообщение 965277)
Да и, кстати, описанный подход к формату будет действенным только для первого уровня иерархи. В более сложной ситуации - когда необходимы наследники от не корневых классов - он не поможет. Останется только композиция.

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


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

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