Здравствуйте, mihailik, Вы писали:
M>Вообще, абстрактный класс предпочтительнее интерфейса в том случае, когда нужно обеспечить стандартное поведение для объектов-потомков. Некоторые методы можно сделать виртуальными, а некоторые — просто public, потому что не все методы нужно перегружать. А интерфейсы подобного контроля не дают.
Есть понятие интерфейс и его контракта. Любое смешивание интерфейса и реализации — это потенциальное зло.
Очень жаль, что дотнет это дупускает. Тем самым сделан шаг назад по сравнению с Корбой и КОМ-ом.
... << RSDN@Home 1.1.2 beta 1 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, AndrewVK, Вы писали:
S>>пусть поступает как я — все переписываю под себя,
AVK> AVK>Вот это обычно и называют кривым дизайном.
Именно. Только это не смешно. Смешно то что людям нужно объяснять такие простые истины.
А результат обычно заключается в том, что из-за мелкой фигни нужно лезть через рефлекшон к закрытым членам или вообще отказываться от использования того или иного кода из-за того, что нельзя заменить маленькую фитюльку.
... << RSDN@Home 1.1.2 beta 1 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Serginio1, Вы писали:
S> Правильно, только S>internal abstract class BTCustomLevel<K,V>
Вот это и есть кривой дизайн. Если это скрытые классы реалзиации, то зачем их вообще делать абстрактными? И почему нет общей асбтракции которую можно переопределить?
В итоге люди воспользовавшиеся твоим классом будут на него намертво завязаны. А из-за неоправданной виртуальности будет страдать производительность.
... << RSDN@Home 1.1.2 beta 1 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>А я и не перегибаю. Чем бы помешал интерфейс в данном случае?
Отсутствие гарантии правильной реализации асинхронных операций. Т.е. сам интерфейс конечно не помешал бы, но при использовании в своих классах я бы наружу выставлял запрос именно Stream а не IStream, поскольку это надежнее, а в плане гибкости ничего на практике не меняется. Хотя совсем правильным было бы вынесение того что реализовано в Stream в отдельный класс-обертку, а интерфейс чтобы описывал только то, что относится непосредственно к самому потоку.
VD>Я эту обертку могу сделать из без Stream. Вопрос в том, что если мне по каким-то причинам неподойдет реализация от МС,
Давай конкретно — по каким причинам тебе может не подойти конкретно Stream.
AVK>>Нет там никакой реализации, касающейся непосредственно самого стрима. Ты бы вместо того чтобы спорить посмотрел что в Stream реализовано. А то эдак можно докатиться до требования реализации собственного формата VMT.
VD>Факт в том, что там уже что-то реализовано. И нет никакой гарантии, что это что-то не окажется лишним/вредным.
Точно так же факт что много чего реализовано в CLR, JIT и "нет никакой гарантии, что это что-то не окажется лишним/вредным". Делать абстрактным все и вся это другая крайность, которая тоже ни к чему хорошему не приведет. Нужно выбирать золотую середину — где то базовые классы, где то интерфейсы.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, <Аноним>, Вы писали:
А>> Да это вообще приватные классы и доступ к ним извне не нужен.
VD>Какие приватные? Ты интерфейс вооей коллекции описал как асбтрактый класс с членами. О чем речь то?
В том то и дело, что не писал я интерфесы колекций. Это не всегда и нужно, как DBTable, но если нужно то прикрутить на public методах недолго. Просто этот вариант с абстрактны классом нужен для того что нижняя ветвь (Child) может быть самой нижней где хранятся данные или родительский подуровень. Так же у IndexBTPP Root может быть как NullLevel или ParentLevel. Просто на разных уровнях хранятся разные данные и по разному обрабатываются. И нужна только внутри всех этих трех классов для внутренней функциональности.
Там кстати ошибка в кастомный класс не нужно вводить поле Child оно только у ParentLevel.
Вот и речь о том, что говорим о другом. А просто показал пример наследования в дженериках, и то что они ни чем не отличаются от обычных классов.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, AndrewVK, Вы писали:
AVK>Отсутствие гарантии правильной реализации асинхронных операций.
Ну, это не серьезно. Любая реализация может быть как нормальной, так и глючной.
AVK> Т.е. сам интерфейс конечно не помешал бы, но при использовании в своих классах я бы наружу выставлял запрос именно Stream а не IStream, поскольку это надежнее,
Вот это уже глупость. При наличии абстракции указывать специализацию нельзя.
AVK> а в плане гибкости ничего на практике не меняется.
Вот указав базовую (минимально подходящую) абстракцию ты точно ничего не теряешь. В обратном случае ничего гарантировать нельзя.
AVK>Давай конкретно — по каким причинам тебе может не подойти конкретно Stream.
А не нужно конкретнее. Это общее правило и его нужно просто применять. Оно просто гарантирует отсуствие граблей.
AVK>Точно так же факт что много чего реализовано в CLR, JIT и "нет никакой гарантии, что это что-то не окажется лишним/вредным".
Это разные вещи. Но гибкость никогда не помешает. Тот же С++ народ любит не за его складность и не противоричивость, а за то, что на нем можно исправить/добавить разные возможности.
AVK> Делать абстрактным все и вся это другая крайность, которая тоже ни к чему хорошему не приведет.
Я как бы не призываю делать все абстрактым. Но если уж делается абстракция, то лучше делать ее по всем правилам, а не лепить горбатого.
Так, например, для скрытых классов реализации абстракция вообще не нужна.
AVK> Нужно выбирать золотую середину — где то базовые классы, где то интерфейсы.
Нужно думать и принимать конкретные решения для конкретных случаев, а не выбирать середину. Но правила примененные с умом еще никому не мешали.
... << RSDN@Home 1.1.2 beta 1 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Serginio1, Вы писали:
S> В том то и дело, что не писал я интерфесы колекций.
1. Зря.
2. Зачем тебе вообще тогда понадобились абстрактные классы?
S> Это не всегда и нужно,
У тебя точно нужно.
S> как DBTable,
Не нужно пенять на то что не доконца понимаешь. DBTable — это частичная реализация разширяющая другую (причем конкретную) реализацию — DataTable. А вот DataTable рализует базовую абстракцию IListSource.
S>но если нужно то прикрутить на public методах недолго.
Блин. Тебе и говорят — что это кривейший дизайн. Ты пользуешся средствами совершенно не по назначению. public-методы и так не трудно сделать реализую интерфейс публичными методами. А вот отсуствие базовой абстракции приведет к тому, что люди взявшие твой класс будут скованны и не смогут его как следует развивать.
S> Просто этот вариант с абстрактны классом нужен для того что нижняя ветвь (Child) может быть самой нижней где хранятся данные или родительский подуровень. Так же у IndexBTPP Root может быть как NullLevel или ParentLevel. Просто на разных уровнях хранятся разные данные и по разному обрабатываются. И нужна только внутри всех этих трех классов для внутренней функциональности. S> Там кстати ошибка в кастомный класс не нужно вводить поле Child оно только у ParentLevel.
Проблема в том, что твой код довольно трудно читать. Да и алгоритмы в нем не примитивные. Давай поступим так. Ты опишешь работу (алгоритм и реализацию) своего класса в небольшой статейке. Я это дело прочту (ну, подправим если что не так...) и постораюсь сделать "правильный" (с моей точки зрения) вариант. А потом сравним все за и против. Ну, и за одно получим интересную статью и проверенную реализацию.
S> Вот и речь о том, что говорим о другом. А просто показал пример наследования в дженериках, и то что они ни чем не отличаются от обычных классов.
Ты показал плохой пример. Абстрактый класс без реализации — это явно кривой дизайн. Да и скрытые абстракции тоже скорее всего плохой подход. Как минимум виртуальные методы тормозят.
... << RSDN@Home 1.1.2 beta 1 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Serginio1, Вы писали:
S> В том то и дело, что не писал я интерфесы колекций. Это не всегда и нужно,
Для коллекций это нужно всегда.
S> как DBTable,
У DataTable есть интерфейс, IListSource. Кроме того DataTable это всего лишь часть коллекции. Другая часть, DataView , реализует IList, IBindingList, ITypedList.
S> но если нужно то прикрутить на public методах недолго.
Тебе недолго. А тому кто будет этим пользоваться просто невозможно. Кроме того просто прикрутить интерфейс недостаточно, необходимо еще и сменить на интерфейс все внешние ссылки.
Здравствуйте, VladD2, Вы писали:
AVK>>Отсутствие гарантии правильной реализации асинхронных операций.
VD>Ну, это не серьезно. Любая реализация может быть как нормальной, так и глючной.
Это серьезно. И дело не в глючности, а в гарантии определенных особенностей внутреннего поведения этих методов.
AVK>> Т.е. сам интерфейс конечно не помешал бы, но при использовании в своих классах я бы наружу выставлял запрос именно Stream а не IStream, поскольку это надежнее,
VD>Вот это уже глупость. При наличии абстракции указывать специализацию нельзя.
Глупость это пихать полную абстракцию ака интерфейс куда не попадя, даже туда где он не нужен.
AVK>>Давай конкретно — по каким причинам тебе может не подойти конкретно Stream.
VD>А не нужно конкретнее.
Нужно, иначе все рассуждения становятся высосанными из пальца. Все таки программирование это больше техническая дисциплина, нежели философская и рассуждать о высших материях конечно интересно, но в конечном итоге нужно все таки ехать.
AVK>>Точно так же факт что много чего реализовано в CLR, JIT и "нет никакой гарантии, что это что-то не окажется лишним/вредным".
VD>Это разные вещи.
Это те же самые вещи, вопрос только в их уровне абстракции, не более того.
VD> Но гибкость никогда не помешает.
Очень спорное утверждение.
VD> Тот же С++ народ любит не за его складность и не противоричивость, а за то, что на нем можно исправить/добавить разные возможности.
Личные проблемы любящего народа. Я лично страстной любовью ни к какому языку не пылаю, поскольку любовь к онному напоминает любовь к молотку или рубанку.
AVK>> Делать абстрактным все и вся это другая крайность, которая тоже ни к чему хорошему не приведет.
VD>Я как бы не призываю делать все абстрактым.
Именно это ты и делал несколькими строчками выше. Мол мне конкретика пофигу, это общее правило.
VD>Так, например, для скрытых классов реализации абстракция вообще не нужна.
Напомню — разговор об IStream. Все остальные случаи меня не интересуют в данный момент.
AVK>> Нужно выбирать золотую середину — где то базовые классы, где то интерфейсы.
VD>Нужно думать и принимать конкретные решения для конкретных случаев,
Золотые слова, только почему то противоречат тому что ты только что писал.
VD> а не выбирать середину.
Выбирать середину это и есть "думать и принимать конкретные решения для конкретных случаев".
VD> Но правила примененные с умом еще никому не мешали.
S>> Вот и речь о том, что говорим о другом. А просто показал пример наследования в дженериках, и то что они ни чем не отличаются от обычных классов.
VD>Ты показал плохой пример. Абстрактый класс без реализации — это явно кривой дизайн. Да и скрытые абстракции тоже скорее всего плохой подход. Как минимум виртуальные методы тормозят.
Постараюсь написать более подробно. Но смысл таков, что за каждый уровень Б++ дерева отвечает класс, для выстроения его в нужном порядке, так как страници не имеют родителя иначе бы приходилось менять их при каждом переносе элементов с одной страници на другую. Но самый нижний уровень имеет отличную реализацию, т.к. хранятся другие данные нежели на верхних уровнях. На в каждой странице хранится счетчик количества элементов и разные массивы: в одном Key,Child а на нижнем Key,Value. В промышленнм стандарте Child и Value это инты и можно обойтись без абстрактных классов передавая только эти инты и в зависимости от уровня вызывать тот или иной метод, но на самом деле виртуальные методы не сильно и тормозят т.к. методы не хилые и о инлайне нет и речи, а т.к. уровней мало то все ссылки на методы сидят в кэше и скорость действительно очень приличная и полностью с применением ООП.
А о плохом дизайне тогда посоветуй как сделать лучше, а я постараюсь объяснить как с могу, но на самом деле очень сложно объяснять в оофлайне. Алгоритм на самом деле простой правда со многими заморочкам но делается за день — два и объяснить с глазу на глаз очень просто и понадобится всего около часа, а затем можно разработать методику описания принципа данного алгоритма.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, LaFlour, Вы писали:
LF>Насколько правила женериков для С++ отличаются/подходят к #-вым? LF>Ну синтаксис и прочее что писал Алексадреску и Джосуттис, насколько они адекватны в свете #вых женериков?
А вот еще повод к размышлению...
При инстанциировании параметризованного класса на C++ компилятор генерит код только для тех методов класса, которые используются (не хочу тут разводить лишнего формализма:) Это позволяет создавать классы, функциональность, которых расширяется (или сужается) в зависимости от значения параметра шаблона.
При этом не проблема, если в классе Strategy в нужный момент не окажется функции f. Просто обломится компиляция.
В связи с тем, что generic'и являются сущностью времени выполнения они не могут предоставлять такую же гибкость. Тут у m$ явно случилась проблема. Но они нашли вполне концептуальное решение. Вместо того, чтобы ожидать, что у параметра шаблона будет наличествовать некий метод, проще сразу потребовать, чтобы параметр шаблона принадлежал некому типу. И это правильно. Но япона мать! Какой же уродский синтаксис для этого выбран! (эмоции...)
public class LinkedList<K,T> where K : IComparable<K>
скопировано из technical article c m$.com
выделенный жирным шрифтом кусок — типичное паскалевское утверждение о том, что K имеет тип IComparable. Кто там у них из delhi в .net пришел? Запамятовал...
Также обошлись и с конструкторами по умолчанию.
Примеры на VB даже смотреть страшно
А вот еще интересный момент.
Дженерик не может унаследоваться от своего параметра a la
template <class T> class A : public T
Вообще, зачем были введены generic'и в .net? Какая преследовалась цель?
Еще вопрос: в каком состоянии находится .net в отношении комитетов по стандартам? Если он все еще принадлежит m$, то это очень прискорбный факт... Потому что они уже сделали, что смогли, а сейчас начнутся извращения...
Что скажет благородная публика?
Здравствуйте, outsourcer, Вы писали:
O>В связи с тем, что generic'и являются сущностью времени выполнения они не могут предоставлять такую же гибкость. Тут у m$ явно случилась проблема. Но они нашли вполне концептуальное решение. Вместо того, чтобы ожидать, что у параметра шаблона будет наличествовать некий метод, проще сразу потребовать, чтобы параметр шаблона принадлежал некому типу. И это правильно. Но япона мать! Какой же уродский синтаксис для этого выбран! (эмоции...)
O>
O>public class LinkedList<K,T> where K : IComparable<K>
O>
O>скопировано из technical article c m$.com
O>выделенный жирным шрифтом кусок — типичное паскалевское утверждение о том, что K имеет тип IComparable. Кто там у них из delhi в .net пришел? Запамятовал...
O>Также обошлись и с конструкторами по умолчанию.
Даже обидно как-то. В Jave'e к этому делу подошли более элегантно.... В жаве типизация параметра шаблона происходит в угловых скобках ( как и должо быть по человечески, на мой взгляд )
AVK>У DataTable есть интерфейс, IListSource. Кроме того DataTable это всего лишь часть коллекции. Другая часть, DataView , реализует IList, IBindingList, ITypedList.
S>> но если нужно то прикрутить на public методах недолго.
AVK>Тебе недолго. А тому кто будет этим пользоваться просто невозможно. Кроме того просто прикрутить интерфейс недостаточно, необходимо еще и сменить на интерфейс все внешние ссылки.
Согласен. Но все листы очень убоги и не раскрывают всех возможностей, а обеспечить функциональность этих интефейсов недолго. Речь пока идет о функциональности Б++ дерева, а все изыски могут немного подождать и реализовать ввиде оберток вокруг существующей реализации.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, AndrewVK, Вы писали:
AVK>Это серьезно. И дело не в глючности, а в гарантии определенных особенностей внутреннего поведения этих методов.
Это не просто не серьезно. Это демагогия. Уж извини.
AVK>Глупость это пихать полную абстракцию ака интерфейс куда не попадя, даже туда где он не нужен.
И кто пихает куда ни попадя? В стриме интерфейс нужен. В классе реализующем универсальную структуру данных вроде Б+-дерева — тоже. Или ты не согласен?
VD>> Но гибкость никогда не помешает.
AVK>Очень спорное утверждение.
Ну, раз ты споришь...
AVK>Личные проблемы любящего народа. Я лично страстной любовью ни к какому языку не пылаю, поскольку любовь к онному напоминает любовь к молотку или рубанку.
Смешно. Твои высказывания по тому же С++ говорят об обратном.
Проблемы же это не "любящего народа", а наши. Так как Шарп той же гибкостью не обладает (к сожалению).
VD>>Я как бы не призываю делать все абстрактым.
AVK>Именно это ты и делал несколькими строчками выше.
Не нужно песен. Я призываю не делать половинчатых решений. Если уш делается абстракция, то пусть она делается чистой.
AVK> Мол мне конкретика пофигу, это общее правило.
Вот только в этом правиле нет призыва все делать абстрактным. Так что н надо ля-ля.
VD>>Так, например, для скрытых классов реализации абстракция вообще не нужна.
AVK>Напомню — разговор об IStream. Все остальные случаи меня не интересуют в данный момент.
Напомню, изначально назговор о применении abstract в классах Серджинио1.
AVK>Золотые слова, только почему то противоречат тому что ты только что писал.
Ничему они не противоречат. Необходимость думать не противоречит наличию правил.
VD>> а не выбирать середину.
AVK>Выбирать середину это и есть "думать и принимать конкретные решения для конкретных случаев".
Тогда мы по разному понимаем слова "выбирать середину".
VD>> Но правила примененные с умом еще никому не мешали.
AVK>Вот именно что с умом.
Я где-то их применял бездумно?
... << RSDN@Home 1.1.2 beta 1 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Serginio1, Вы писали:
S> А о плохом дизайне тогда посоветуй как сделать лучше,
Еще раз повторяю. Создай небольшую статейку объясняющую что и как. Тогда я постораюсь помочь, так как буду понимать что у тебя и зачем. Без этого на разбирательства уйдет очень много времени. Ну, и за одно убьем двух зайцев, так как создадим статью которую будет не грешно опубликовать в журнале и на сайте.
В эту статью хорошо бы включить описания и других твоих реализаций. Я как раз сейчас пишу статью о коллекциях в дотнете. Твоя статья стала бы прекрасным дополнением, так сказать для "продвинутых".
Только не выкладывай все сразу в конфу. Должна же быть какая-то эксклюзивность.
S> а я постараюсь объяснить как с могу, но на самом деле очень сложно объяснять в оофлайне.
Ты пиши. Я поправлю все что нужно. Главное, чтобы была четко сформулирована идея.
S> Алгоритм на самом деле простой правда со многими заморочкам но делается за день — два и объяснить с глазу на глаз очень просто и понадобится всего около часа, а затем можно разработать методику описания принципа данного алгоритма.
Ну, тода давай сделаем в два этапа. Сначала опишешь как сможешь. Потом объяснишь лично. А потом я поправлю первый вариант и получится интересная и нужная статья.
... << RSDN@Home 1.1.2 beta 1 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
AVK>>Это серьезно. И дело не в глючности, а в гарантии определенных особенностей внутреннего поведения этих методов.
VD>Это не просто не серьезно. Это демагогия. Уж извини.
Как знаешь.
AVK>>Глупость это пихать полную абстракцию ака интерфейс куда не попадя, даже туда где он не нужен.
VD>И кто пихает куда ни попадя? В стриме интерфейс нужен.
Зачем?
VD> В классе реализующем универсальную структуру данных вроде Б+-дерева — тоже. Или ты не согласен?
С первым нет, со вторым да.
AVK>>Личные проблемы любящего народа. Я лично страстной любовью ни к какому языку не пылаю, поскольку любовь к онному напоминает любовь к молотку или рубанку.
VD>Смешно. Твои высказывания по тому же С++ говорят об обратном.
Цитаты в студию.
AVK>> Мол мне конкретика пофигу, это общее правило.
VD>Вот только в этом правиле нет призыва все делать абстрактным.
Общее правило, в котором не указано когда его применять означает что применять надо всегда.
AVK>>Напомню — разговор об IStream. Все остальные случаи меня не интересуют в данный момент.
VD>Напомню, изначально назговор о применении abstract в классах Серджинио1.
По поводу его классов я уже высказался. То же письмо, на которое ты ответил было по поводу твоего высказывания на тему Stream.
VD>>> а не выбирать середину.
AVK>>Выбирать середину это и есть "думать и принимать конкретные решения для конкретных случаев".
VD>Тогда мы по разному понимаем слова "выбирать середину".
Здравствуйте, VladD2, Вы писали:
AVK>>Тебе и сейчас ничего не мешает. В базовом Stream реализованы только асинхронное чтение/запись и ReadByte/WriteByte, которые по сути просто обертки над Read/Write. VD>Нет батенька, базовая абстракция отсуствует и я уже не могу делать "чистые" реализации. Грамотнее было бы ввести интерфейс, а в Stream реализовать некоторые его методы.
Кстати, из презентации ADO.NET 1.2:
ADO.NET v1.0/1.1 was based on interfaces
Not enough to write provider-agnostic code
Hard to evolve
We’re introducing a common model
Abstract base classes instead of interfaces
Better versioning story
3rd party providers can reuse our common code
They can even re-use our connection pooler
Provider-independent apps fully enabled at the API level
This is an extension, no breaking changes
Кроме того, в ATL обычной практикой являются классы IXXXImpl, реализующие некую дефолтную функциональность интерфейса. В .NET это не так удобно из-за отсутствия множественного наследования (Control.ActiveXImpl — типичный пример такой проблемы), но для классов с одним основным интерфейсом вполне оправдано.