Здравствуйте, Воронков Василий, Вы писали:
ВВ>Ничего не понял. Зачем мне отнаследованный интерфейс приводить к базовому да еще "безопасно"?
Для полиморфизму.
ВВ> Зачем мне вообще приводить интерфейс к чему-либо?
Аналогично.
Странный у тебя какой то вопрос. Наследование интерфейсов ничем в плане предназначения не отличается от наследования контрактов обычных классов при наследовании классов.
... << RSDN@Home 1.2.0 alpha 5 rev. 52 on Windows 7 6.1.7601.65536>>
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Собственно, сабж. Что это дает-то в принципе? На первый взгляд кажется, что это вообще скорее вредно.
Наследование вообще вредно, а наследование интерфейсов выявляет наиболее неприятные черты этого приёма.
И всё же без него нельзя обойтись, т.к. это единственный способ (в mainstream, во всяком случае) выразить средствами языка отношение "общее-частность". Конечно, средствами языка полиморфизм не ограничивается — при желании возможно хоть собственное преобразование типов в духе IBird.AsADish() ввести (с произвольной группой преобразований), но поскольку непротиворечивость подобной модели программисты не умеют проверяют ни сами, ни с помощью компьютера — такое из методологии разработки исключается и заменяется старым добрым наследованием.
если же наследование интерфейса не выражает отношение абстракции — к примеру, как тут говорили: "нужно добавить метод — давайте из IFoo сделаем IFoo2" — тут уже идёт один вред для архитектуры.
автору мессенджерных имплементаций и быть на 100% уверенным, что он описал SkypeMessenger именно как SkypeMessenger : IFileSender, IMessenger; — этот код на его стороне. У вас получается, что, хотя бы в принципе, кто-то может поддержать отправку файлов без текста, даже если вы такой сценарий хотите запретить. А я его запрещаю контрактно и сплю спокойно.
Здравствуйте, AndrewVK, Вы писали:
ВВ>>Ничего не понял. Зачем мне отнаследованный интерфейс приводить к базовому да еще "безопасно"? AVK>Для полиморфизму.
Можно привести пример? Я не понимаю, зачем мне приводить интерфейс к базовому, и как это связано с полиморфизмом.
ВВ>> Зачем мне вообще приводить интерфейс к чему-либо? AVK>Аналогично. AVK>Странный у тебя какой то вопрос. Наследование интерфейсов ничем в плане предназначения не отличается от наследования контрактов обычных классов при наследовании классов.
Реализация интерфейсов классами — да. Но сами-то интерфейсы зачем друг от друга наследовать? В случае с классами — это хотя бы виртуальные функции и перегрузка. А с интерфейсами? Что дает наследование?
Здравствуйте, b-3, Вы писали:
b-3>И всё же без него нельзя обойтись, т.к. это единственный способ (в mainstream, во всяком случае) выразить средствами языка отношение "общее-частность".
Почему единственное? Интерфейс — всегда общее. Реализация — всегда частность. Понятно, что из интерфейсов можно построить некую иерархию, но зачем? Можно просто разобрать эту иерархию, и все будет работать точно так же. Собственно, зачем интерфейсы по отношению друг к другу должны находиться в отношении "общее-частностность"? Что это дает?
Здравствуйте, SV., Вы писали:
>А я его запрещаю контрактно и сплю спокойно.
Обобщенно говоря, если вы хотите, чтобы любой объект, поддерживающий интерфейс B, ВСЕГДА поддерживал интерфейс A (в частности, но не только, обязать имплементатора интерфейса B имплементировать интерфейс A), вам нужно наследование B от A. Если такой потребности нет, наследование интерфейсов не нужно, вредно и так далее.
SV.>Каждый раз констрейнт копипакостить? Или один раз правильно контракт определить?
Что вы собрались копипастить? AdvancedMessenger — это конкретный неполиморфный метод, который вполне может возвращать конкретную реализацию.
SV.>В любом случае, ваш код не эквивалентен моему. Вы, например, не можете отдать одну интерфейсную часть SV.>автору мессенджерных имплементаций и быть на 100% уверенным, что он описал SkypeMessenger именно как SkypeMessenger : IFileSender, IMessenger; — этот код на его стороне. У вас получается, что, хотя бы в принципе, кто-то может поддержать отправку файлов без текста, даже если вы такой сценарий хотите запретить. А я его запрещаю контрактно и сплю спокойно.
Ну да, поэтому я должен отнаследовать слона от ежа. Необходимость всегда реализовывать отсылку текста при реализации отсылки файлов как бы сводит на нет все ваши абстракции. На фига мне запрещать что-то? Я ожидаю (IFileSender IMessageSender) и это вынесено в контракт. И этого более чем достаточно.
При вашем же подходе придут еще три орла и нареализуют продолжение такой иерархии. В итоге окажется, что для того, чтобы реализовать один нужный мне интерфейс мне нужно реализовать еще 25 ненужных методов путем throw NotImplementedException, когда они при этом не нужны ни мне, ни библиотеке, с которой я работаю. И эту замечательную картину мы и имеем в полном объеме в том же дотнете.
А вам ведь на самом деле нужно было всего лишь это:
interface IMessenger<T> where T : IMessage
{
void Send(T);
}
Здравствуйте, Воронков Василий, Вы писали:
DG>>>>то функция сможет вернуть только или IEnumerable, или ICollection, и придется явно кастить, чтобы получить доступ к другому интерфейсу ВВ>>>Что в этих мейнстрим языках уже решается через генерики F>> Как это решается через генерики? ВВ>GetItems? Там вообще непонятно, зачем возвращать интерфейс. Это же не полиморфный метод, он вполне конкретную штуку возвращает. Если метод полиморфный, то нужные интерфейсы просто навешиваются в констрейнтах.
Уффф. Нет, что-то я в GetItems не вижу генериков... Или слепой или не знаю. Можно как-то по человечески объяснить, что имеется ввиду? Пожалуйста.
Здравствуйте, fddima, Вы писали:
DG>>>>>то функция сможет вернуть только или IEnumerable, или ICollection, и придется явно кастить, чтобы получить доступ к другому интерфейсу ВВ>>>>Что в этих мейнстрим языках уже решается через генерики F>>> Как это решается через генерики? ВВ>>GetItems? Там вообще непонятно, зачем возвращать интерфейс. Это же не полиморфный метод, он вполне конкретную штуку возвращает. Если метод полиморфный, то нужные интерфейсы просто навешиваются в констрейнтах. F> Уффф. Нет, что-то я в GetItems не вижу генериков... Или слепой или не знаю. Можно как-то по человечески объяснить, что имеется ввиду? Пожалуйста.
GetItems — это в примере неполиморфный метод. Возвращайте конкретный тип.
Или уж слепите класс. ICollection — это вообще по сути скорее single inheritance класс, а не интерфейс.
Здравствуйте, SV., Вы писали:
SV.>Здравствуйте, SV., Вы писали: >>А я его запрещаю контрактно и сплю спокойно. SV.>Обобщенно говоря, если вы хотите, чтобы любой объект, поддерживающий интерфейс B, ВСЕГДА поддерживал интерфейс A
Зачем это делать? Есть какие-то причины для этого, кроме экспериментов над людьми?
Мне достаточно задекларировать список интерфейсов, которые я хочу получить — все.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>GetItems — это в примере неполиморфный метод. Возвращайте конкретный тип. ВВ>Или уж слепите класс. ICollection — это вообще по сути скорее single inheritance класс, а не интерфейс.
Ок, откатимся назад.
DG>то функция сможет вернуть только или IEnumerable, или ICollection, и придется явно кастить, чтобы получить доступ к другому интерфейсу ВВ>Что в этих мейнстрим языках уже решается через генерики
Вто КАК это решается через генерики?
Здравствуйте, fddima, Вы писали:
DG>>то функция сможет вернуть только или IEnumerable, или ICollection, и придется явно кастить, чтобы получить доступ к другому интерфейсу ВВ>>Что в этих мейнстрим языках уже решается через генерики F> Вто КАК это решается через генерики?
Я в третий раз уже пишу, что GetItems через генерики не реализуется, но там и интерфейс не нужен.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>>>Ничего не понял. Зачем мне отнаследованный интерфейс приводить к базовому да еще "безопасно"? AVK>>Для полиморфизму.
ВВ>Можно привести пример?
Пример полиморфизма на наследовании?
AVK>>Странный у тебя какой то вопрос. Наследование интерфейсов ничем в плане предназначения не отличается от наследования контрактов обычных классов при наследовании классов.
ВВ>Реализация интерфейсов классами — да.
Да при чем тут реализация? Полиморфизм обеспечивается именно наследованием контрактов.
ВВ> Но сами-то интерфейсы зачем друг от друга наследовать?
Точно за тем же самым.
ВВ> В случае с классами — это хотя бы виртуальные функции и перегрузка. А с интерфейсами?
Тоже самое.
ВВ> Что дает наследование?
Безопасный апкастинг.
Мне так кажется, что ты куда то удалился совсем и не видишь очевидного. Если без интерфейсов, то ты берешь кучу разнотипных классов, выносишь общую часть в базовый класс, после чего можешь писать абстрактные алгоритмы только поверх базы.
С интерфейсами все тоже самое. Выносишь общую часть разных интерфейсов в одного предка и после этого ее можно использовать в более абстрактных алгоритмах.
Теперь что касается констрейнтов в дженериках в дотнете. Во-первых, когда проектировали интерфейсы, никаких дженериков еще не было. Во-вторых с наследованием просто писанины меньше, перечислять всю потребную кучу интерфейсов в большой иерархии может быть накладно, модифицировать при появлении еще одного интерфейса всю цепочку вызовов тоже будет весело. В-третих наследование задает готовую структуру отношений интерфейса, что удобно, повышает читабельность и накладывает дополнительные ограничения. К примеру, интерфейс IButton не имеет смысла без интерфейса IControl, поэтому проще всего его отнаследовать, и тогда любая реализация IButton будет реализовывать IControl.
... << RSDN@Home 1.2.0 alpha 5 rev. 52 on Windows 7 6.1.7601.65536>>
Здравствуйте, Воронков Василий, Вы писали:
ВВ>В итоге окажется, что для того, чтобы реализовать один нужный мне интерфейс мне нужно реализовать еще 25 ненужных методов путем throw NotImplementedException,
И это ОЧЕНЬ хорошо, поскольку когда клиент вашего кода вызовет не нужный ВАМ, но нужный ЕМУ метод, и метод выкинет NotImplementedException, то долго не придется искать, кого бить по наглой рыжей морде. Что касается нужности, все наоборот: контрактную часть описывает архитектор системы, а "орлы" ее реализуют. И не дело "орлов" принимать решения на уровне архитектуры, по крайней мере, не посоветовавшись с остальными.
>когда они при этом не нужны ни мне, ни библиотеке, с которой я работаю. И эту замечательную картину мы и имеем в полном объеме в том же дотнете.
ВВ>А вам ведь на самом деле нужно было всего лишь это:
ВВ>
ВВ>interface IMessenger<T> where T : IMessage
ВВ>{
ВВ> void Send(T);
ВВ>}
ВВ>
Как с архитектором я бы с вами работать не стал. Интерфейсы должны быть кристально прозрачны, и служить документацией. Из моего интерфейсного кода понятно, что есть объекты, некоторые из которых умеют отправлять только текст, а другие — и текст, и файлы, но нет таких, которые умеют отправлять только файлы. Мессенджер, текст, файл — понятия из реальной жизни, поэтому код читается как азбука. В вашем коде и текст, и файл зачем-то обобщаются до абстрактного "сообщения". Отправляя тексты и файлы через скайп, вы в самом деле держите в уме, что и то, и другое — по сути одно и то же, некоторое "сообщение"? Или вы отправляете тексты и файлы?
Здравствуйте, AndrewVK, Вы писали:
ВВ>>>>Ничего не понял. Зачем мне отнаследованный интерфейс приводить к базовому да еще "безопасно"? AVK>>>Для полиморфизму. ВВ>>Можно привести пример? AVK>Пример полиморфизма на наследовании?
Пример вот этого:
"Отнаследованный интерфейс ты можешь привести к базовому безопасно. Классический полиморфизм."
Я не понимаю, зачем мне приводить интерфейсы, и как это помогает полиморфизму.
AVK>>>Странный у тебя какой то вопрос. Наследование интерфейсов ничем в плане предназначения не отличается от наследования контрактов обычных классов при наследовании классов. ВВ>>Реализация интерфейсов классами — да. AVK>Да при чем тут реализация? Полиморфизм обеспечивается именно наследованием контрактов.
Полиморфизм в ООП технически обеспечивается динамическим диспатчем метода по типу первого аргумента.
Это в общем-то можно и вообще без контрактов.
В случае с контрактами достаточно иметь возможность писать конкретные реализации контрактов, но зачем сами контракты между собой наследовать? Это уж точно никак не "обеспечивает" полиморфизм, если есть возможность указать, какие именно контракты мы ожидаем на входе.
ВВ>> Что дает наследование? AVK>Безопасный апкастинг.
А зачем мне нужен этот апкастинг? В каких случаях он используется?
AVK>Мне так кажется, что ты куда то удалился совсем и не видишь очевидного. Если без интерфейсов, то ты берешь кучу разнотипных классов, выносишь общую часть в базовый класс, после чего можешь писать абстрактные алгоритмы только поверх базы. AVK>С интерфейсами все тоже самое. Выносишь общую часть разных интерфейсов в одного предка и после этого ее можно использовать в более абстрактных алгоритмах. AVK>Теперь что касается констрейнтов в дженериках в дотнете. Во-первых, когда проектировали интерфейсы, никаких дженериков еще не было. Во-вторых с наследованием просто писанины меньше, перечислять всю потребную кучу интерфейсов в большой иерархии может быть накладно, модифицировать при появлении еще одного интерфейса всю цепочку вызовов тоже будет весело. В-третих наследование задает готовую структуру отношений интерфейса, что удобно, повышает читабельность и накладывает дополнительные ограничения. К примеру, интерфейс IButton не имеет смысла без интерфейса IControl, поэтому проще всего его отнаследовать, и тогда любая реализация IButton будет реализовывать IControl.
IButton, IControl — вообще какие-то странные интерфейсы. Ну да ладно.
Положим, они бы не были отнаследованы. И что, какая проблема с этим? Мы что-то важное потеряем в результате?
Здравствуйте, SV., Вы писали:
ВВ>>В итоге окажется, что для того, чтобы реализовать один нужный мне интерфейс мне нужно реализовать еще 25 ненужных методов путем throw NotImplementedException, SV.>И это ОЧЕНЬ хорошо, поскольку когда клиент вашего кода вызовет не нужный ВАМ, но нужный ЕМУ метод, и метод выкинет NotImplementedException, то долго не придется искать, кого бить по наглой рыжей морде. Что касается нужности, все наоборот: контрактную часть описывает архитектор системы, а "орлы" ее реализуют. И не дело "орлов" принимать решения на уровне архитектуры, по крайней мере, не посоветовавшись с остальными.
Ничего не понял. В моем случае как раз никто не получит по морде. Потому что клиент моего кода явно задекларирует те интерфейсы, которые ему ДЕЙСТВИТЕЛЬНО нужны, а не получит бомбу с NotImplementedException.
SV.>Как с архитектором я бы с вами работать не стал.
ОК, если у нас откроются вакансии, то я вас не позову.
SV.>Интерфейсы должны быть кристально прозрачны, и служить документацией. Из моего интерфейсного кода понятно, что есть объекты, некоторые из которых умеют отправлять только текст, а другие — и текст, и файлы, но нет таких, которые умеют отправлять только файлы. Мессенджер, текст, файл — понятия из реальной жизни, поэтому код читается как азбука. В вашем коде и текст, и файл зачем-то обобщаются до абстрактного "сообщения". Отправляя тексты и файлы через скайп, вы в самом деле держите в уме, что и то, и другое — по сути одно и то же, некоторое "сообщение"? Или вы отправляете тексты и файлы?
Если я работаю с чем-то конкретным, конкретно со скайпом, если я отправляю конктретно текст и конкретно файлы, то и весь код у меня получается очень даже конкретный, а совсем не полиморфный. А казалось бы — о полиморфизме речь, нет?
В моем варианте "документацией" служат именно те интерфейсы, которые и должны служить документацией в данном случае — контракты сообщений. А скайп или СМС — это, вообще говоря, "абстракции" уже другого уровня.
Здравствуйте, Воронков Василий, Вы писали:
>>>А я его запрещаю контрактно и сплю спокойно. SV.>>Обобщенно говоря, если вы хотите, чтобы любой объект, поддерживающий интерфейс B, ВСЕГДА поддерживал интерфейс A
ВВ>Зачем это делать? Есть какие-то причины для этого, кроме экспериментов над людьми? ВВ>Мне достаточно задекларировать список интерфейсов, которые я хочу получить — все.
Затем, что хороший ОО-код отражает объективную реальность, а плохой ОО-код — своего автора. В жизни есть мессенджеры, которые умеют отправлять тексты, но не умеют файлы, например, СМСный гейт, но нет таких мессенджеров, которые умеют отправлять файлы, но не умеют тексты. Мой код это отражает. Ваш — нет.
Здравствуйте, SV., Вы писали:
SV.>Затем, что хороший ОО-код отражает объективную реальность, а плохой ОО-код — своего автора. В жизни есть мессенджеры, которые умеют отправлять тексты, но не умеют файлы, например, СМСный гейт, но нет таких мессенджеров, которые умеют отправлять файлы, но не умеют тексты. Мой код это отражает. Ваш — нет.
Я не знаю, что именно отражает ваш код, и какие именно мессенджеры существуют в жизни — а вы же по ходу уверены, что точно и наверняка знаете какие абстракции будут правильны в 100% случаев. Вот только в 100% эти абстракции оказываются неправильными. Потому что ОО код никакого отношения к объективной реальности не имеет.
Но дело даже не в этом. Я предложил подумать и высказать реальные причины, почему что-то реализовано так, а не иначе. Вы же в ответ выдали "ОО-код отражает объективную реальность". Не стоило, право, и начинать