Re[9]: Множественное наследование
От: tarkil Россия http://5209.copi.ru/
Дата: 21.03.05 08:40
Оценка: +1
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Самый простой объект — это действительно структура (члены структуры, узлы графа, отдельные указатели и т.д.).


Самый простой объект — целостный, в котором не выделена внутренняя структура.

СГ>Самая простая динамическая структура связанных объектов — это список.

СГ>Самый простой способ объединения объектов в один блок — массив на уровне языка программирования.

Разница между блоком и динамической структурой неясна. С моей т.з. самым простым методом объединения является неупорядоченная коллекция. Либо упорядоченная. Без завязки на то, как она будет храниться: массивом, списком, деревом...

СГ>Самый простой взгляд на взаимодейсвие между объектами — это их композиция, а уж никак не "наследование скрытого состояния".


Это, пожалуй, верно. Но, добавлю, что композиция объектов порождает третий объект, поведение которого требует доопределения. Композиция проста, но требует уточнения.

СГ>Так что "глубокий изъян" это, видимо, стремление к максимальной простоте.


Простота сама по себе является достоинством только, если с ней удобно работать. Для построения любого алгоритма достаточно двух конструкций: простого следования и условного перехода. Проще некуда. Нафиг-нафиг такую простоту!
--
wbr, Peter Taran
Re[13]: Множественное наследование
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 21.03.05 08:53
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Здравствуйте, eao197, Вы писали:


E>>Это я и так понимаю, запоминается writter куда? В атрибут. И, вероятно, не public-атрибут.


СГ>Естественно. Но тут нет никакого наследования от какого-либо самостоятельного класса объектов. Здесь речь идет о композиции объектов.


А я и не говорил про наследование в этом случае. Перечитай еще раз внимательно мои слова.

E>>Сергей, вы не понимаете суть вопроса. Пусть сначала Formatter был связан с writter-ом, который связан с файлом. Затем какому-то потомку захотелось перевязать этот же Formatter на writter, который связан с pipe. Можно ли такое допускать?

E>>А почему нет? Пусть у меня есть Formatter, который строит XML и передает его в writter. Затем я делаю потомка для этого Formatter, который перед построением XML переводит все строки в UTF-8. Разве это запрещено? И нужно ли моему Utf8XmlFormatter-у знать, где XmlFormatter хранит ссылку на writter?

СГ>Нет никаких потомков! Класс Formatter не является потомком от класа Writer. Это разные классы.


Где я говорил о том, что Formatter является потомком Writter?
Я спросил про две вещи:

1. Можно ли делать свою иерархию классов для Formatter?
2. Если можно, то имеет ли право производный Formatter сменить ссылку на writter, которая была сохранена в базовом классе Formatter?

СГ>Самостоятельному объекту formatter ничего не известно о том куда самостоятельный объект writer осуществляет вывод.

СГ>
СГ>          +--->---Reader---> >---Scanner--->---+  
СГ>          |                                    |
СГ>Carrier---+                                    +---Client
СГ>          |                                    | 
СГ>          +---<---Writer---< <---Formatter--<--+
СГ>

СГ>Carrier, Reader, Writer, Scanner, Formatter, Client — это композиция из 6 разных объектов (классы которых не связаны друг с другом никаким отношением наследования). Стрелочки на рисунке обозначают поток информации от/в носител(я) Carrier, в роли которого может выступать кто угодно (File, Stream, Socket, ...) из/в Client.

СГ>Этот паттерн проектирования называется Carrier-Rider-Mapper.

СГ>Reader и Writer — это Rider-ы
СГ>Scanner и Formatter — это Mapper-ы

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

СГ>Каждый Carrier реализует свои собственные Reader и Writer (нет никакого наследования от других самостоятельных классов объектов).


Весело. Если в Unix-е чтение из файла, pipe и сокета ничем не отличается друг от друга, то зачем мне делать 3 разных Carrier (FileCarrier, PipeCarrier, SockerCarrier), а для них еще и 6 Reader/Writter (FileReader, FileWritter, PipeReader, PipeWritter, SocketReader, SocketWritter)?
Имхо, в этом случае ООП и не пахнет. А если и пахнет, то чем-то прогнившим.

СГ>Каждый Client реализует нужные только ему Scanner и Formatter (нет никакого наследования от других самостоятельных классов объектов).


Т.е. если клиенту MailAgent нужно читать из сокета SMTP трафик, то он должен создать свои Scanner и Formatter. И если я хочу создать свой SMSForwarder, который использует SMTP транспорт, то я так же должен создать собственные Scanner и Formatter? Даже не смотря на то, что их функциональность будет практически такой же как и для MailAgent?

СГ>Количество реализаций равно N + M, где N — количество разных Carrier-ов, а M — количество разных Client-ов. Если не использовать этот паттерн, а заставлять каждого клиента уметь работать непосредственно с каждым карриером, то количество реализаций взаимодействия из суммы N + M превратится в произведение N * M, что неэкономно.


Имхо, как раз то, что ты предлагаешь и приведет к N*M.
... << RSDN@Home 1.1.4 beta 4 rev. 303>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[10]: Множественное наследование
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 21.03.05 09:14
Оценка:
Здравствуйте, tarkil, Вы писали:

T>Здравствуйте, Сергей Губанов, Вы писали:


СГ>>Самый простой объект — это действительно структура (члены структуры, узлы графа, отдельные указатели и т.д.).


T>Самый простой объект — целостный, в котором не выделена внутренняя структура.


Разумеется. Если переменные этой записи не экспортируются, то такой объект снаружи выглядит как раз как объект с не выделеной внутренней структурой. Вот так:
DEFINITION Module1

TYPE
  Object = RECORD END;

END Module1.

Что находится внутри записи известно только самому модулю, для всех остальных тип Module1.Object — это вещь в себе.


СГ>>Самая простая динамическая структура связанных объектов — это список.

СГ>>Самый простой способ объединения объектов в один блок — массив на уровне языка программирования.

T>Разница между блоком и динамической структурой неясна.


Динамическая структура динамически изменяется. Блок — фиксирован, его можно целиком создать и целиком о нем потом забыть.

СГ>>Самый простой взгляд на взаимодейсвие между объектами — это их композиция, а уж никак не "наследование скрытого состояния".


T>Это, пожалуй, верно. Но, добавлю, что композиция объектов порождает третий объект, поведение которого требует доопределения. Композиция проста, но требует уточнения.


Нет не порождает. Третий объект нужен в языках не имеющих сборки мусора только для того чтобы ввести между объектами отношение хозяин/раб и создавать/уничтожать первые два объекта синхронно с третьим — так проще за памятью следить.

СГ>>Так что "глубокий изъян" это, видимо, стремление к максимальной простоте.


T>Простота сама по себе является достоинством только, если с ней удобно работать. Для построения любого алгоритма достаточно двух конструкций: простого следования и условного перехода. Проще некуда. Нафиг-нафиг такую простоту!


В таком случа добавляют "...но не проще." Целиком: "Сделай так просто на сколько это возможно, но не проще".
Re[14]: Множественное наследование
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 21.03.05 09:25
Оценка:
Здравствуйте, eao197, Вы писали:

E>1. Можно ли делать свою иерархию классов для Formatter?

E>2. Если можно, то имеет ли право производный Formatter сменить ссылку на writter, которая была сохранена в базовом классе Formatter?

Делайте на здоровье и то и другое.

E>...зачем мне делать 3 разных Carrier...

E>...я так же должен создать собственные Scanner и Formatter?...

Не делайте на здоровье ни того и ни другого.
Re[15]: Множественное наследование
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 21.03.05 10:24
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Здравствуйте, eao197, Вы писали:


E>>1. Можно ли делать свою иерархию классов для Formatter?

E>>2. Если можно, то имеет ли право производный Formatter сменить ссылку на writter, которая была сохранена в базовом классе Formatter?

СГ>Делайте на здоровье и то и другое.


Тогда следующий вопрос: если базовый тип какого-то Formatter-а не допускает простой смены writter-а в процессе работы, то как он может запретить делать это производному классу? Например, Formatter шифрует сообщение каким-либо блочным шифром. Для этого сообщение разбивается на блоки кратные, скажем, 8 байтам. Но вот в очередном сообщении оказался хвостик из 5 байт. Если поступит следующее сообщение, то Formatter просто объеденит эти 5 байт с 3-мя первыми байтами очередного сообщения и продолжит свою работу. Если Formatter выполнит операцию flush, то он добавить к 5-ти оставшимся байтам 3 нулевых байта и зашифрует их.

Но в этом случае Formatter должен защищать свою ссылку на writter-а, чтобы какой-то из нерадивых потомков не сменил writter-а пока есть оставшиеся от предыдущего сообщения байты. Имхо, логично здесь хранить ссылку на writter-а в виде private атрибута. А доступ к нему предоставлять производным классам через protected методы.


E>>...зачем мне делать 3 разных Carrier...

E>>...я так же должен создать собственные Scanner и Formatter?...

СГ>Не делайте на здоровье ни того и ни другого.


Что значит не делать? Как же тогда паттерн Carrier-Rider-Mapper? Или это Zonnon-specific штука?
... << RSDN@Home 1.1.4 beta 4 rev. 303>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[9]: Множественное наследование
От: Кодт Россия  
Дата: 21.03.05 13:20
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

К>>У меня складывается впечатление, что есть какой-то глубокий изъян в методологии изучения и практики программирования. В основном он присущ изучению структурно-ориентированных языков. Вот что это за изьян:

К>>Мышление об объектах как о россыпи деталей (члены структуры, узлы графа, отдельные указатели и т.д.).
К>>Отсюда — написание функций, работающих со списком через указатель на головной узел; динамические массивы на уровне языка, управление которыми (перевыделение памяти, например) доступно кому попало; вот ещё добавляется боязнь скрытого состояния базовых объектов.

СГ>Самый простой объект — это действительно структура (члены структуры, узлы графа, отдельные указатели и т.д.).

СГ>Самая простая динамическая структура связанных объектов — это список.
СГ>Самый простой способ объединения объектов в один блок — массив на уровне языка программирования.
СГ>Самый простой взгляд на взаимодейсвие между объектами — это их композиция, а уж никак не "наследование скрытого состояния".

СГ>Так что "глубокий изъян" это, видимо, стремление к максимальной простоте.


Ты сам сказал "... но не проще".
Если я делаю декомпозицию задачи "мне нужен контейнер с последовательным двусторонним доступом, бла-бла-бла"
до "вот тебе объекты-узлы, собирай из них орграф-список, следи за целостностью и т.д."
то заказчик не порадуется. И меня не порадует.
В учебных целях (для понимания алгортимов реализации всей этой механики) — ради бога. Но в прикладных — первое, что нужно будет сделать — это найти наиболее абстрактный (в смысле — не привязанный к нюансам реализации) интерфейс.
Перекуём баги на фичи!
Re[16]: Множественное наследование
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 21.03.05 13:27
Оценка:
Здравствуйте, eao197, Вы писали:

E> А доступ к нему предоставлять производным классам через protected методы.


Я вот что хочу сказать. Вы конечно можете наследоваться от классов как хотите, но я "проповедую" такой способ: Если уж наследоваться, то всегда это делать только от абстрактных классов. А от полноценных самостоятельных самодостаточных классов не наследоваться — вместо этого использовать композицию с уже готовыми объектами таких классов. Я считаю что так более правильно. У меня все.

E> Как же тогда паттерн Carrier-Rider-Mapper? Или это Zonnon-specific штука?


Zonnon тут не причем. Паттерн Carrier-Rider-Mapper был придуман Клеменсом Шиперски
Из документации к BlackBox:

The Carrier-Rider-Mapper separation goes back to a research project ["Insight ETHOS: On Object-Orientation in Operating Systems"; Clemens Szyperski; vdf, Zürich, 1992, ISBN 3 7281 1948 2] predating BlackBox. This project used several design patterns and design rules (e.g., avoidance of implementation inheritance) that are also described in Design Patterns. In the Design Patterns terminology, a Rider-Mapper combination (or Carrier-Mapper combination if there is no rider) forms a bridge pattern.

Re[10]: Множественное наследование
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 21.03.05 13:32
Оценка:
Здравствуйте, Кодт, Вы писали:

К>...первое, что нужно будет сделать — это найти наиболее абстрактный (в смысле — не привязанный к нюансам реализации) интерфейс.


Естественно.
Re[17]: Множественное наследование
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 21.03.05 13:37
Оценка: +1
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Здравствуйте, eao197, Вы писали:


E>> А доступ к нему предоставлять производным классам через protected методы.


СГ>Я вот что хочу сказать. Вы конечно можете наследоваться от классов как хотите, но я "проповедую" такой способ: Если уж наследоваться, то всегда это делать только от абстрактных классов. А от полноценных самостоятельных самодостаточных классов не наследоваться — вместо этого использовать композицию с уже готовыми объектами таких классов. Я считаю что так более правильно. У меня все.


Да вы, батенька, экстремист!

Похоже, что больше я вряд ли смогу чего добавить.
... << RSDN@Home 1.1.4 beta 4 rev. 303>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[10]: Множественное наследование
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.03.05 17:27
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Скорее помогли бы конструкции типа

C>
C>class A implements I1, I2, I3
C>{
C>    [delegate default I1] I1Impl impl1;
C>};
C>

C>То есть делегировать непереопределенные методы из интерфейса I1 в
C>I1Impl. Реализуется такое до смешного просто, компилятору нужно
C>сгенерировать стабы методов такого вида:
C>
C>void I1Method1()
C>{
C>    impl1->I1Method1();
C>}
C>int I1Method2()
C>{
C>    return impl1->I1Method2();
C>}
C>....
C>

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

Зачем компилятору что-то делегировать, когда он может просто скопировать код методов?
... << RSDN@Home 1.1.4 beta 4 rev. 359>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: Множественное наследование
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.03.05 17:27
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Самое смешное что в шарпе for действительно синтаксический сахар, на уровне IL превращающийся в while. Далеко не все декомпиляторы умеют использовать for.


while тоже нет. Есть конструкция проверки значения и конструкция перехода.
... << RSDN@Home 1.1.4 beta 4 rev. 359>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Множественное наследование
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.03.05 17:27
Оценка:
Здравствуйте, eao197, Вы писали:

VD>>Private-наследование уже выброшено. И, кстати, подилом. Дурь это.


E>Из C++ выброшено?

E>А где про это прочитать можно?

На С++ свет клином не сошелся. Хотя согласен, говорить "выброшено" не корректно. Проще сказать, что кроме С++ его нигде толком то и нет.
... << RSDN@Home 1.1.4 beta 4 rev. 359>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: Множественное наследование
От: Cyberax Марс  
Дата: 21.03.05 18:24
Оценка: +2 -1
VladD2 пишет:

> C>Получится примерно то же самое, что и трейты, но для этого не нужно

> C>вводить никаких особых изменений в язык.
> Зачем компилятору что-то делегировать, когда он может просто
> скопировать код методов?

Копирование — это плохо. Вдобавок, мое решение более гибкое — я могу
менять реализацию делегата в run-time. Да и вообще, по-моему, гораздо
более простое решение.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[12]: Множественное наследование
От: prVovik Россия  
Дата: 21.03.05 19:53
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Копирование — это плохо. Вдобавок, мое решение более гибкое — я могу

C>менять реализацию делегата в run-time.
Да и вообще, по-моему, гораздо
C>более простое решение.

А вот это как раз самое вкусное.
... << RSDN@Home 1.1.4 @@subversion >>
лэт ми спик фром май харт
Re[10]: Множественное наследование
От: Sinclair Россия https://github.com/evilguest/
Дата: 22.03.05 04:16
Оценка: +1
Здравствуйте, Cyberax, Вы писали:

C>Скорее помогли бы конструкции типа

C>
C>class A implements I1, I2, I3
C>{
C>    [delegate default I1] I1Impl impl1;
C>};
C>

C>То есть делегировать непереопределенные методы из интерфейса I1 в
C>I1Impl. Реализуется такое до смешного просто, компилятору нужно
C>сгенерировать стабы методов такого вида:
Смешно перестает быть тогда, когда происходит обратное приведение. Что вернет выражение (A)(I2)(new A())?
... << RSDN@Home 1.1.4 beta 4 rev. 347>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[11]: Множественное наследование
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 22.03.05 08:35
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>while тоже нет. Есть конструкция проверки значения и конструкция перехода.


Которые от while отличаются исключительно внешним видом
... << RSDN@Home 1.1.4 beta 4 rev. 369>>
AVK Blog
Re[11]: Множественное наследование
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 22.03.05 09:57
Оценка:
VladD2 пишет:
> Зачем компилятору что-то делегировать, когда он может просто скопировать
> код методов?

Во-первых, это может привести к
существенному увеличению объёма кода.

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

--
Andrei N.Sobchuck
JabberID: andreis@jabber.ru. ICQ UIN: 46466235.
Posted via RSDN NNTP Server 1.9
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[12]: Множественное наследование
От: GlebZ Россия  
Дата: 22.03.05 10:12
Оценка:
Здравствуйте, Andrei N.Sobchuck, Вы писали:

ANS>Во-первых, это может привести к

ANS><span class='lineQuote level1'>ANS&gt;существенному увеличению</span> объёма кода.
Шаблоны тоже увеличивают код. Но сейчас уже никто и не жалуется.

С уважением, Gleb.
Re[11]: Множественное наследование
От: Кодт Россия  
Дата: 22.03.05 17:44
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

S>Смешно перестает быть тогда, когда происходит обратное приведение. Что вернет выражение (A)(I2)(new A())?


Вот поэтому в COM агрегация устроена с прибамбасами. Чтобы семейство агрегатов и главного объекта выдавало наружу интерфейсы, QueryInterface'абельные друг к другу. Для этого каждый агрегат знает Controlling IUnknown главного объекта и все запросы по AddRef, Release, QueryInterface перенаправляет к нему.
Перекуём баги на фичи!
Re[12]: Множественное наследование
От: Sinclair Россия https://github.com/evilguest/
Дата: 23.03.05 10:53
Оценка:
Здравствуйте, Кодт, Вы писали:
К>Вот поэтому в COM агрегация устроена с прибамбасами. Чтобы семейство агрегатов и главного объекта выдавало наружу интерфейсы, QueryInterface'абельные друг к другу. Для этого каждый агрегат знает Controlling IUnknown главного объекта и все запросы по AddRef, Release, QueryInterface перенаправляет к нему.
Я в курсе. COM как раз явственно демонстрирует тот факт, что для корректного решения проблемы каждый класс, который может стать жертвой агрегации (класс-примесь) обязан реализовывать специальные интерфейсы. В принципе, их реализация ничего сверхъестественного не представляет и даже может быть сгенерирована компилятором. Однако, если мы говорим уже о .Net, то возникают некоторые занятные особенности. В частности, вместо явного вызова QueryInterface, который может быть делегирован аггрегирующему объекту путем подмены реализации, в коде будет использован специальный опкод каста. Т.е. для корректного примешивания нужно просматривать весь код примеси в поисках специфических операций, и корректно заменять его на что-то.
... << RSDN@Home 1.1.4 beta 4 rev. 347>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.