Здравствуйте, DarkGray, Вы писали: DG>Проблем становится меньше, но они все равно остаются. Если, конечно, речь идет о сохранении контракта родителя, а не просто о наследовании реализации.
Вопрос — в том, что считать контрактом. Вот, к примеру, на некотором уровне абстракции IEnumerable<T> и Nullable<T> реализуют один и тот же "контракт". Что, естественно, никак не выражено, да и невыразимо в системе типов .Net.
DG>У наследника для некоторых методов может меняться тип результата, что разрушает контракт родителя.
Это если вы так обозначили тип результата в контракте. DG>Для пары квадрат/прямоугольник такого метода сходу не скажу, а для пары эллипс/круг он известен.
DG>Метод "Получить_Оси_Симметрии" для эллипса возвращает тип Конечное_множество_известного_заранее_размера<2, Ось_Симметрии>, а для круга возвращает тип Неисчислимое_множество<Ось_Симметрии>.
Ну, мы же понимаем, что этот метод должен вернуть вам неисчислимое множество сразу же у эллипса, которому не повезло иметь совпадающие фокусы. Даже без введения типа "круг". Поэтому метод обязан с самого начала возвращать множество, а уж какова будет его мощность — сие зависит от параметров фигуры.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Serginio1, Вы писали:
S> А тем, что я этот сгенеренный код легко могу подправить. Иногда проще исправить в одном двух местах в сгенеренном коде, чем городить навороченный алгоритм всевозможных вариантов. А когда ты этот код перегенерируешь ты точно вспомнишь, где ты раньше правил?
S>Ну и опять же я даю это для себя любимого. А кто не хочет брать эту обработку, тот может пользоваться другими инструментами. Нет жесткой зависимости.
Ну да. Любой код можно выбросить... Вообще не понял к чему ты.
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Serginio1, Вы писали: S>>Как я уже и писал выше проще наследоваться от абстрактного класса Фигура. А по твоему подходу можно наследоваться хоть от треугольника, все равно виртуальные методы перекрываются. Это ничем не отличается от интерфейсов. Все таки наследование это в первую очередь наследование существующей реализации и структуры полей, с добавлением дополнительных свойств(полей) и методов. S>Нет. Я не хочу опять заниматься очередным ликбезом, поэтому отвечу кратко: наследование — это отношение "is-a". И наследование реализации — один из худших видов наследования. S>А про то, что проще, а что сложнее, рассуждать вообще не имеет смысла до тех пор, пока не поставлена задача.
Ну да. Вот например тебе в наследство достался член. Но ты то ли из-за каких то проблем с размером решил этот член отрезать и вместо него пришить новый.
Ну во первых это опасно для здоровья, а во вторых как многими доказано размер не имеет значения. Зачем плодить лишние сущности?
А задач таких полно. Например Control, Документы в БД (можно выделять разные виды доументов (складские, финансовые итд), у которых есть одинаковые сущности и поведение. Легче в базовом классе прописать реализацию, а в новых только дополнять или изменять только те методы специфичные для данного документа. Например печать. И то в процессе печати могут использоваться в основном неперекрытые методы, так и перекрываемы, для формирования дополнительного вывода секций. Наследованиеи полиморфизмвыделены отдельно. Например в 1С приходится использовать полиморфизм через использование названия одинаковых методов и свойств. Но это далеко не ООП
S>В реальных решениях все эти иерархии фигур, столь популярные в учебниках, отсутствуют за ненадобностью. В реальной графической программе у вас скорее всего будет что-то вроде одного класса Shape, который состоит из набора прямых, дуг, и кривых Безье. А все "фигуры" будут описываться всего лишь конструкторами.
Ну не везде и не всегда. Я вот сейчас работаю на мебельной фабрике. Там есть программы для оптимального расположения фигур для резки, с минимальными количествами отходов.
Но в основном эти фигуры являются прямоугольниками и нет большого смысла городить огород со сложными фигурами. В любом случае их проще вписать в прямоугольники для упрощения алгоритма (криволинейный крой).
И квадрат в этом случае ничем от прямоугольника не отличается.
Хотя есть и программы которые работают со сложными фигурами, но вот алгоритм там совсем другой, более сложный и затратный. Но вот им в реальных условиях не пользуются.
Если для тебя наследование реализации — один из худших видов наследования, то для меня все наоборот. Меня интересует минимум написания кода при введении нового элемента в иерархию.
Кстати в Delphi есть такой подход как виртуальные методы класса. S>>С Введением интерфейсов, перекрытие в ООП ушло на второй план. S>Ну-ну.
Ну и в чем различие между Интерфейсом и наследованием VMT если все методы перекрываются? Только в организации доступа к этим таблицам.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, Serginio1, Вы писали:
S>> А тем, что я этот сгенеренный код легко могу подправить. Иногда проще исправить в одном двух местах в сгенеренном коде, чем городить навороченный алгоритм всевозможных вариантов. WH> А когда ты этот код перегенерируешь ты точно вспомнишь, где ты раньше правил?
А вот я сравню новый код со старым. и изменю (добавлю) только тот код который требуется. S>>Ну и опять же я даю это для себя любимого. А кто не хочет брать эту обработку, тот может пользоваться другими инструментами. Нет жесткой зависимости. WH>Ну да. Любой код можно выбросить... Вообще не понял к чему ты.
Ну я к тому, что ваш спор сводится в общем к одному. DSL это хорошо, до тех пор пока его не приходится поддерживать не авторами DSL.
И здесь каждый манагер для себя выбирает какой код проще поддерживать. Ведь как правильно было замечено на создание уходит меньше времени, чем на его поддержку.
Если общие DSL изучают все, то для доморощенного нужно тратить время на обучение, вникание и не всем это посильно. Самому (и не только мне одному) кстати проще переписать, чем поддерживать чей то невнятный код.
Ну а любой код не выбрасывается, так как из старого можно выборочно построить новый. Ну и тренировка ума.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, DarkGray, Вы писали:
IO>>Не подходит для эллипса, который есть окружностью. DG>во-первых, это вопрос терминологии. Или эллипс есть невырожденный эллипс с a != b и a > 0, b > 0,
Странно когда родительский класс не представляет частные случаи, которые представляют потомки. В таких случаях потомок "не есть" родитель. Значит потомок не представляет подмножество родителя, а родитель не есть более общее понятие относительно потомка. И наследование здесь не должно применяться.
Можно конечно унаследовать квадрат от крокодила, все перекрыть... Но мы же говорим о проблемах ООП при правильном применении, а не о проблемахантипаттернов.
DG> или эллипс есть обобщенный эллипс, включающий в себя в том числе и все вырожденные случаи: круг (a=b a,b!= 0), точка (a=b=0), "двойной" отрезок (a=0,b != 0 или a!=0, b=0)
Именно такой, каким он описан в математике, не плодим сущности.
DG>во-вторых, проблема в любом случае остается и для пары обобщенный эллипс и обобщенный круг. Потому что для обобщенного эллипса метод "Получить_Оси_Симметрии" имеет возвращаемый тип Union<Конечное_множество_известного_заранее_размера<2, Ось_Симметрии>, Неисчислимое_множество<Ось_Симметрии>>, а для обобщенного круга данный метод имеет возвращаемый тип Неисчислимое_множество<Ось_Симметрии>
Такой тип не нужен, так как Ваш Union может представить такие обьекты подмножеством своих значений.
Может в таких случаях метод потомка должен возвращать подтип метода предка?
Здравствуйте, Serginio1, Вы писали:
S>Если общие DSL изучают все
Потому что Domain общий.
S>, то для доморощенного нужно тратить время на обучение, вникание и не всем это посильно.
Конкретный Domain тоже нужно изучить.
Легче это сделать когда уже есть хоть какой-то язык.
S> Самому (и не только мне одному) кстати проще переписать, чем поддерживать чей то невнятный код.
Либу тоже проще переписать? Зачастую проще переписать, потому что сложно (или лень) понять
S>> Самому (и не только мне одному) кстати проще переписать, чем поддерживать чей то невнятный код. IO>Либу тоже проще переписать? Зачастую проще переписать, потому что сложно (или лень) понять
Да нет стараешься понять (это же и тренировка ума, и просмотр новых подходов) и считаю, что переписывать код это последнее средство. Переписывать это тоже не легкий путь. Так или иначе все равно приходится разбираться с кодом. Так вот иногда взвесив затраты на переписывание и поддержку делаешь то, что для тебя выгодней.
Как и в случае с DSL все зависит от конкретной ситуации. Все плюсы и минусы здесь уже были озвучены. А решение принимает ответственный за проект.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали: S> Ну да. Вот например тебе в наследство достался член. Но ты то ли из-за каких то проблем с размером решил этот член отрезать и вместо него пришить новый. S>Ну во первых это опасно для здоровья, а во вторых как многими доказано размер не имеет значения. Зачем плодить лишние сущности? Идиотские некорректные аналогии обсуждать не будем.
S> А задач таких полно. Например Control, Документы в БД (можно выделять разные виды доументов (складские, финансовые итд), у которых есть одинаковые сущности и поведение. Легче в базовом классе прописать реализацию, а в новых только дополнять или изменять только те методы специфичные для данного документа. Например печать. И то в процессе печати могут использоваться в основном неперекрытые методы, так и перекрываемы, для формирования дополнительного вывода секций.
Вопрос уместности ООП в системах документооборота остаётся открытым. ООП привносит много проблем. В частности, в ООП тип (класс) объекта предполагается неизменным, а в документообороте совершенно нормальной является смена типа. Точнее, на разных этапах жизенного цикла документ реализует существенно различные контракты, так что делать их частью типа — бессмысленно.
S> Ну не везде и не всегда. Я вот сейчас работаю на мебельной фабрике. Там есть программы для оптимального расположения фигур для резки, с минимальными количествами отходов. S>Но в основном эти фигуры являются прямоугольниками и нет большого смысла городить огород со сложными фигурами. В любом случае их проще вписать в прямоугольники для упрощения алгоритма (криволинейный крой).
Ну вот видите, в вашем алгоритме нет никаких иерархий фигур. Фигура определяется реальной формой (поликривая) и её bounding rectangle. S>И квадрат в этом случае ничем от прямоугольника не отличается.
Как, впрочем, и от круга, эллипса, звезды Соломона и профиля Руссиновича. S>Хотя есть и программы которые работают со сложными фигурами, но вот алгоритм там совсем другой, более сложный и затратный. Но вот им в реальных условиях не пользуются.
И даже в нём нет никаких иерархий фигур. S> Если для тебя наследование реализации — один из худших видов наследования, то для меня все наоборот. Меня интересует минимум написания кода при введении нового элемента в иерархию.
Совершенно верно. Именно поэтому наследование реализации — зло: при нём введение нового элемента в иерархию может затронуть неограниченный объём кода. Ведь элемент может появиться не только в листе. Любое изменение в базовом классе начинает распространяться на всех наследников как степной пожар.
S>Кстати в Delphi есть такой подход как виртуальные методы класса.
Я в курсе. И связано это с понятием "ссылки на класс", которого нет в других языках программирования. Фактически, в Delphi есть две параллельных иерархии наследования — классов и метаклассов. В дотнете Хейльсберг решил этим не задуряться.
S> Ну и в чем различие между Интерфейсом и наследованием VMT если все методы перекрываются? Только в организации доступа к этим таблицам.
Вы слишком много внимания уделяете несущественным деталям, вроде VMT и организации доступа. Это вам мешает.
Наследование реализации — это в том числе и наследование состояния, чего нет в случае реализации интерфейса.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Serginio1, Вы писали: S>> Ну да. Вот например тебе в наследство достался член. Но ты то ли из-за каких то проблем с размером решил этот член отрезать и вместо него пришить новый. S>>Ну во первых это опасно для здоровья, а во вторых как многими доказано размер не имеет значения. Зачем плодить лишние сущности? S>Идиотские некорректные аналогии обсуждать не будем.
S>> А задач таких полно. Например Control, Документы в БД (можно выделять разные виды доументов (складские, финансовые итд), у которых есть одинаковые сущности и поведение. Легче в базовом классе прописать реализацию, а в новых только дополнять или изменять только те методы специфичные для данного документа. Например печать. И то в процессе печати могут использоваться в основном неперекрытые методы, так и перекрываемы, для формирования дополнительного вывода секций. S>Вопрос уместности ООП в системах документооборота остаётся открытым. ООП привносит много проблем. В частности, в ООП тип (класс) объекта предполагается неизменным, а в документообороте совершенно нормальной является смена типа. Точнее, на разных этапах жизенного цикла документ реализует существенно различные контракты, так что делать их частью типа — бессмысленно.
Ну вот я занимаюсь этими контрактами. Например для складских документов будет одинаковый алгоритм списания по партиям, одинаковый набор реквизитов в табличной части итд. Где можно выделить одного общего предка.
S>> Ну не везде и не всегда. Я вот сейчас работаю на мебельной фабрике. Там есть программы для оптимального расположения фигур для резки, с минимальными количествами отходов. S>>Но в основном эти фигуры являются прямоугольниками и нет большого смысла городить огород со сложными фигурами. В любом случае их проще вписать в прямоугольники для упрощения алгоритма (криволинейный крой). S>Ну вот видите, в вашем алгоритме нет никаких иерархий фигур. Фигура определяется реальной формой (поликривая) и её bounding rectangle. S>>И квадрат в этом случае ничем от прямоугольника не отличается. S>Как, впрочем, и от круга, эллипса, звезды Соломона и профиля Руссиновича. S>>Хотя есть и программы которые работают со сложными фигурами, но вот алгоритм там совсем другой, более сложный и затратный. Но вот им в реальных условиях не пользуются. S>И даже в нём нет никаких иерархий фигур.
Не совсем. Там уже проще выделять базовые фигуры на которые фигура может быть похожа и в которую её можно преобразовать. Например прямоугольники треугольники и прочие выпуклытые вогнутые фигуры. Ты их классифицируешь и подбираешь фигуры по критериям меньшего незаполненного пространства. И применение алгоритмов можно вести от простого к сложному. Из двух треугольников или двух вогнутых и выпуклых можно получить прямоугольник. итд
S>> Если для тебя наследование реализации — один из худших видов наследования, то для меня все наоборот. Меня интересует минимум написания кода при введении нового элемента в иерархию. S>Совершенно верно. Именно поэтому наследование реализации — зло: при нём введение нового элемента в иерархию может затронуть неограниченный объём кода. Ведь элемент может появиться не только в листе. Любое изменение в базовом классе начинает распространяться на всех наследников как степной пожар.
А что в этом плохого, если на начальном этапе была ошибка? Ты исправил в одном месте вместо во всей иерархии. Для примера есть единый код который дергает виртуальные методы. Ну и понадобилось что то изменить в этом методе например журнал регистрации действий. Чем это плохо. Все зависит от правильности архитектуры приложения.
Для примера с документами. Например изнаально был только один метод списания ФИФО, но в будущем понадобилось списание по ЛИФО. Так изменяя алгоритм в базовом классе ты приводишь к нужному поведению всех документов.
Ты кстати по поводу контролов почему то не прошелся.
S>>Кстати в Delphi есть такой подход как виртуальные методы класса. S>Я в курсе. И связано это с понятием "ссылки на класс", которого нет в других языках программирования. Фактически, в Delphi есть две параллельных иерархии наследования — классов и метаклассов. В дотнете Хейльсберг решил этим не задуряться.
А может ему не дали?
S>> Ну и в чем различие между Интерфейсом и наследованием VMT если все методы перекрываются? Только в организации доступа к этим таблицам. S>Вы слишком много внимания уделяете несущественным деталям, вроде VMT и организации доступа. Это вам мешает. S>Наследование реализации — это в том числе и наследование состояния, чего нет в случае реализации интерфейса.
Ну так в твоем случае прямоугольник квадрат наследования ни состояния ни реализации нет.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Ikemefula, Вы писали:
I>Про то и речь, что квадрат здесь ровно один, задаётся ровно двумя точками. Третий параметр обязателен только для прямоугольника и один единственный прямоугольник невозможно задать только этими двумя точками, нужен и третий параметр который ты сам же и ввёл.
И? Чем нам не подходит класс Rectangle для описания квадратов? Создание отдельного класса квадратов в таком случае имеет смысл только в очень специфической ситуации: если мы имеем дело с миллиардами квадратов, хранящихся в оперативной памяти. Тогда создание отдельного класса позволит (причём если храним их не смешивая с прямоугольниками, иначе на полиморфизм пойдёт та же самая память) уменьшить расход памяти на 20%. При этом увеличив сложность кода, так что это имеет смысл только при обнаружение узкого места по памяти, а иначе является классической преждевременной оптимизацией. Для всех остальных случаев использование класса Rectangle для описания квадрата будет вполне адекватным.
I>Недавно ты говорил "все тоже самое". Оказывается что не всё, а есть целый набор свойств которые есть следствие равных сторон, например, биссектрисы пересекаются под прямым углом.
Хыхы, это не следствие равенства сторон. А у прямоугольника они не под прямым что ли пересекаются? ))) Равенство сторон приводит только к общей точке пересечения.
I>Ну если ты все еще сомневаешься, то покажи окружность, вписаную в прямоугольник(который квадратом не является) ну и покажи как унифицировать такой интерфейс.
С точки зрения математики окружность можно вписать не в любой четырёхугольник, так что подобный разговор вообще бессмыслен.
Здравствуйте, alex_public, Вы писали:
_>И? Чем нам не подходит класс Rectangle для описания квадратов? Создание отдельного класса квадратов в таком случае имеет смысл только в очень специфической ситуации:
Правильно, какими и бывают оптимизации, коих обычно несчетное множество. Не в каждой конечно программе.
I>>Недавно ты говорил "все тоже самое". Оказывается что не всё, а есть целый набор свойств которые есть следствие равных сторон, например, биссектрисы пересекаются под прямым углом.
_>Хыхы, это не следствие равенства сторон.
Не хочется проводить ликбез по планиметрии, но т.к. треугольник из двух сторон и диагонали опаньки! равнобедренный а у него биссектриса из угла между равными сторонами пересекает стретью торону под прямым углом.
> А у прямоугольника они не под прямым что ли пересекаются? ))) Равенство сторон приводит только к общей точке пересечения.
Нет и это очевидно любому кто учил геометрию. Эту разницу можно использовать для оптимизации.
Собтсвенно после такого ляпа можно и разговор заканчивать, но я нынче добр
I>>Ну если ты все еще сомневаешься, то покажи окружность, вписаную в прямоугольник(который квадратом не является) ну и покажи как унифицировать такой интерфейс.
_>С точки зрения математики окружность можно вписать не в любой четырёхугольник, так что подобный разговор вообще бессмыслен.
С точки зрения разработки это можно использовать для вычислений. Кстати, ты в курсе, что у квадрата еще две дополнительные оси симметрии и это тоже можно использовать для оптимизации ? Привет векторная алгебра !
Похоже, ты отрицаешь, что свойства квадрата и прямоугольника отличаются
Мне просто кажется ты привык к своим задачам и ничего дальше даже не хочешь рассматривать. Я собственно не утверждаю, что класс квадрат надо вводить в любом случае. В качестве оптимизаций — запросто, существенно упрощает логику, т.е. не надо будет обкладывать логику проверками, исключениями и прочей мутью, когда большая часть вычислений завязана на свойства именно квадрата, а не прямоугольника.
Здравствуйте, Serginio1, Вы писали:
S> Ну вот я занимаюсь этими контрактами. Например для складских документов будет одинаковый алгоритм списания по партиям, одинаковый набор реквизитов в табличной части итд. Где можно выделить одного общего предка.
Где-то можно, где-то — нельзя. Причём весь "алгоритм списания по партиям" построен исключительно на публичной информации из документа, поэтому его можно выделить во внешний код. S> Не совсем. Там уже проще выделять базовые фигуры на которые фигура может быть похожа и в которую её можно преобразовать. Например прямоугольники треугольники и прочие выпуклытые вогнутые фигуры. Ты их классифицируешь и подбираешь фигуры по критериям меньшего незаполненного пространства. И применение алгоритмов можно вести от простого к сложному. Из двух треугольников или двух вогнутых и выпуклых можно получить прямоугольник. итд
И как это относится к ООП-иерархии? Свойства фигуры определяются её формой, а не тем, от кого она отнаследована.
S> А что в этом плохого, если на начальном этапе была ошибка?
Того, что теперь изменилось поведение неопределённого количества классов. И то, что вам кажется исправлением ошибки, в одном из наследников приведёт к нарушению логики.
S> Для примера с документами. Например изнаально был только один метод списания ФИФО, но в будущем понадобилось списание по ЛИФО. Так изменяя алгоритм в базовом классе ты приводишь к нужному поведению всех документов.
А если бы с самого начала метод списания был во внешнем хелпер-методе, то ничего изменять в базовом классе бы вообще не пришлось. И не потребовалось бы перетестировать всех наследников на предмет того, не сломался ли кто-то из них из-за некорректно перекрытого виртуального метода. Более того, можно было бы применять обе стратегии в зависимости от конкретных условий — например, документы до часа Ч проводятся по FIFO, а после — по LIFO. Подобная гибкость при наследовании труднодостижима.
S>Ты кстати по поводу контролов почему то не прошелся.
Неинтересно.
S> Ну так в твоем случае прямоугольник квадрат наследования ни состояния ни реализации нет.
Я привёл два случая.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Ikemefula, Вы писали:
_>>Хыхы, это не следствие равенства сторон. I>Не хочется проводить ликбез по планиметрии, но т.к. треугольник из двух сторон и диагонали опаньки! равнобедренный а у него биссектриса из угла между равными сторонами пересекает стретью торону под прямым углом.
А я нигде и не утверждал, что они пересекаются не под прямым углом. Я сказал лишь что это равенство сторон не является необходимым условием этого.
>> А у прямоугольника они не под прямым что ли пересекаются? ))) Равенство сторон приводит только к общей точке пересечения. I> Нет и это очевидно любому кто учил геометрию. Эту разницу можно использовать для оптимизации. I>Собтсвенно после такого ляпа можно и разговор заканчивать, но я нынче добр
Ну раз этот мой ляп очевиден даже школьнику и тем более раз ты нынче добр, то тебе конечно же не составит труда продемонстрировать один прямоугольник, биссектрисы которого пересекаются не под прямым углом? )
I>Мне просто кажется ты привык к своим задачам и ничего дальше даже не хочешь рассматривать. Я собственно не утверждаю, что класс квадрат надо вводить в любом случае. В качестве оптимизаций — запросто, существенно упрощает логику, т.е. не надо будет обкладывать логику проверками, исключениями и прочей мутью, когда большая часть вычислений завязана на свойства именно квадрата, а не прямоугольника.
Если у нас в задаче есть только квадраты, то естественно что никакие прямоугольники и не должны всплывать. Если же есть и то и другое, то логично использовать один класс, обобщающий их свойства. За исключением редкой ситуации, когда возникает узкое место по ресурсам.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Serginio1, Вы писали:
S>> Ну вот я занимаюсь этими контрактами. Например для складских документов будет одинаковый алгоритм списания по партиям, одинаковый набор реквизитов в табличной части итд. Где можно выделить одного общего предка. S>Где-то можно, где-то — нельзя. Причём весь "алгоритм списания по партиям" построен исключительно на публичной информации из документа, поэтому его можно выделить во внешний код.
Во во когда видишь такой код в 1С сразу вспоминаешь об ООП. Там такое нагорождение в этих внешнем коде. Опять же есть куча возможностей определить реализацию в базовом классе внутри которых дергаются абстрактные методы, которые переопределяются в наследниках, что реализовывать в хэлперах без строгой иерархии (контрактов) проблематично. Опять же чем больше инструментов тем лучше.
Кстати и в 1С стараются применять утинную типизацию. Но это костыли.
S>> Не совсем. Там уже проще выделять базовые фигуры на которые фигура может быть похожа и в которую её можно преобразовать. Например прямоугольники треугольники и прочие выпуклытые вогнутые фигуры. Ты их классифицируешь и подбираешь фигуры по критериям меньшего незаполненного пространства. И применение алгоритмов можно вести от простого к сложному. Из двух треугольников или двух вогнутых и выпуклых можно получить прямоугольник. итд S>И как это относится к ООП-иерархии? Свойства фигуры определяются её формой, а не тем, от кого она отнаследована.
Ну вот форма может быть близкой к треугольнику, прямоугольнику, овалу, серпу итд. И соответственно наследоваться от этих фигур. Либо иметь функцию трансформации в такую фигуру.
S>> А что в этом плохого, если на начальном этапе была ошибка? S>Того, что теперь изменилось поведение неопределённого количества классов. И то, что вам кажется исправлением ошибки, в одном из наследников приведёт к нарушению логики.
Я уже приводил пример со списанием по партиям. Какое там нарушение логики, если правильно спроектировани базовый класс, а наследники отвечают за дополнительную часть?
Другое дело, что документы могут быть смешанными. Например и складскими так и взаиморасчеты с клиентами. И приходится применять разные тактики. Например можно трансформировать в объект другого класса, можно применить интерфейсы итд. Организация развитой иерархии сложное дело. И найти оптимальное решение достаточно сложное и трудоемкое решение. Пример тому эволюция конфигураций в 1С.
Но чем больше инструментов тем проще работать.
S>> Для примера с документами. Например изнаально был только один метод списания ФИФО, но в будущем понадобилось списание по ЛИФО. Так изменяя алгоритм в базовом классе ты приводишь к нужному поведению всех документов. S>А если бы с самого начала метод списания был во внешнем хелпер-методе, то ничего изменять в базовом классе бы вообще не пришлось. И не потребовалось бы перетестировать всех наследников на предмет того, не сломался ли кто-то из них из-за некорректно перекрытого виртуального метода. Более того, можно было бы применять обе стратегии в зависимости от конкретных условий — например, документы до часа Ч проводятся по FIFO, а после — по LIFO. Подобная гибкость при наследовании труднодостижима.
А зачем тестировать если они являются наследниками и у них общая часть для списаний по партиям? Я уже выше писал про такие хэлперы в 1С.
А кто мешает стратегию применить в базовом классе? Интерфейсы в большинстве случаев более сложный вариант и нет у него преймуществ перед иерархией классов. S>>Ты кстати по поводу контролов почему то не прошелся. S>Неинтересно.
А мне очень нравится организация Контрололв.
S>> Ну так в твоем случае прямоугольник квадрат наследования ни состояния ни реализации нет. S>Я привёл два случая.
В твоем варианте наследоваться можно хоть от точки. Это к наследованию никакого отношения не имеет. Полиморфизм это наследование VMT, куда ты можешь втыкать, что угодно.
При этом можно легко получать мужчину из женщины или наоборот. А можно и гермофродитов. По принципу если бы у бабушки был ..., то она стала бы дедушкой.
Но на самом деле есть абстрактный класс человек вбирающий общий не половые признаки, и его легко описать. А вот описание половых признаков будет значительно меньшим дополнением.
То есть ты считаешь что ООП не нужно? Да здравствует утинная типизация (интерфейсы это просто типизированный контракт). И мыслить не реальными категориями наследования которые присутствуют в реальной жизни, а городить костыли непонятно зачем.
Зачем кастрировать ООП до уровня интерфейсов?
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, alex_public, Вы писали: I>>Не хочется проводить ликбез по планиметрии, но т.к. треугольник из двух сторон и диагонали опаньки! равнобедренный а у него биссектриса из угла между равными сторонами пересекает стретью торону под прямым углом.
_>А я нигде и не утверждал, что они пересекаются не под прямым углом. Я сказал лишь что это равенство сторон не является необходимым условием этого.
Имелось ввиду, что диагональ есть биссектриса.
I>>Мне просто кажется ты привык к своим задачам и ничего дальше даже не хочешь рассматривать. Я собственно не утверждаю, что класс квадрат надо вводить в любом случае. В качестве оптимизаций — запросто, существенно упрощает логику, т.е. не надо будет обкладывать логику проверками, исключениями и прочей мутью, когда большая часть вычислений завязана на свойства именно квадрата, а не прямоугольника.
_>Если у нас в задаче есть только квадраты, то естественно что никакие прямоугольники и не должны всплывать. Если же есть и то и другое, то логично использовать один класс, обобщающий их свойства. За исключением редкой ситуации, когда возникает узкое место по ресурсам.
С этого все и начиналось — "В качестве оптимизаций".
Кстати часто нужно добавить свойство метод и в место того, что бы добавить это в базовый класс приходится во всех наследниках добавлять это поле, не забыть в хэлпере его проинициализировать.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали: S> Во во когда видишь такой код в 1С сразу вспоминаешь об ООП. Там такое нагорождение в этих внешнем коде. Опять же есть куча возможностей определить реализацию в базовом классе внутри которых дергаются абстрактные методы, которые переопределяются в наследниках, что реализовывать в хэлперах без строгой иерархии (контрактов) проблематично. Опять же чем больше инструментов тем лучше.
Нет. Лучше — когда выполняются принципы хорошего дизайна.
S>Кстати и в 1С стараются применять утинную типизацию. Но это костыли.
При чём тут утиная типизация?
S> Ну вот форма может быть близкой к треугольнику, прямоугольнику, овалу, серпу итд. И соответственно наследоваться от этих фигур. Либо иметь функцию трансформации в такую фигуру.
Простите, это чушь. "Функция трансформации" определяется не тем, кто от кого отнаследован, а степенью близости к определённой форме. К примеру, овал одной формы будет близок к прямоугольнику, а другой формы — к кругу. Под близостью я понимаю отношение площади фигуры к площади покрывающей её фигуры "упрощённой" формы. Ну так вот в таком подходе совершенно непонятно, от кого наследовать овал — от прямоугольника или от круга. Это показывает ущербность идеи вообще применять наследование для этих целей.
S> Я уже приводил пример со списанием по партиям. Какое там нарушение логики, если правильно спроектировани базовый класс, а наследники отвечают за дополнительную часть?
А откуда вы знаете, что наследники корректно отвечают за "дополнительную" часть? Без перетестирования вы этого никак не узнаете.
S>Другое дело, что документы могут быть смешанными. Например и складскими так и взаиморасчеты с клиентами. И приходится применять разные тактики. Например можно трансформировать в объект другого класса, можно применить интерфейсы итд.
А можно спроектировать так, чтобы не вносить лишних зависимостей. Трансформировать в объект другого класса нельзя — вы потеряете идентичность. Если у вас зародилась идея поменять класс, сохранив идентичность, то лучше убейте её в зародыше, т.к. она взорвёт всю объектную модель. Вы потеряете типобезопасность — т.е. какие-то ссылки на объект класса А внезапно окажутся ссылками на объект класса Б. В лучшем случае вы получите cast exception в рантайме; в более плохом вы будете применять неподходящие методы.
Поверьте мне на слово — я норматив на мастера спорта в этом выпиливании лобзиком по вазелину выполнил ещё тогда, когда 1с под стол пешком ходил.
S>Но чем больше инструментов тем проще работать.
Нет. Преумножение сущностей без необходимости только затрудняет работу.
S>А кто мешает стратегию применить в базовом классе? Интерфейсы в большинстве случаев более сложный вариант и нет у него преймуществ перед иерархией классов.
Я вам объяснил уже, почему не применить. Потому что документ не должен решать, какова стратегия партионного учёта. Сегодня она одна, а завтра — другая. Документ при этом остаётся документом.
S> А мне очень нравится организация Контрололв.
А мне — нет. Всю жизнь меня бесило то, что в одних контролах есть, скажем, дабл-клик евент, а в других — нету. И всё, сиди кури. Или допиливай очередного наследника, в которого ты копи-пейстом будешь переносить эту убогую стейт-машину.
Ну, теперь-то мы знаем, как это правильно делать, слава Rx. Но в "чистом ООП" иерархии контролов — полная хрень.
S> В твоем варианте наследоваться можно хоть от точки. Это к наследованию никакого отношения не имеет. Полиморфизм это наследование VMT, куда ты можешь втыкать, что угодно.
Я вам ещё раз намекну, что мысли в категориях VMT мешают вам понять суть вещей. Это ненужные подробности.
S> То есть ты считаешь что ООП не нужно?
Я считаю, что большинство программистов неверно понимают ООП — спасибо идиотской пропаганде заблуждений. S>Да здравствует утинная типизация (интерфейсы это просто типизированный контракт). И мыслить не реальными категориями наследования которые присутствуют в реальной жизни, а городить костыли непонятно зачем.
В реальной жизни нет категорий наследования, которые поддерживаются в ООП. Вас обманули.
Те же типы документов построить в дерево крайне тяжело. И да, "утиная типизация" для них подходит лучше, чем многая другая. Грубо говоря потому, что от документа для какого-либо процесса обычно требуется иметь некий набор атрибутов. При этом у одного типа документов могут быть атрибуты А и Б, у другого — Б и В, а у третьего — А и В. И кого от кого тут наследовать — совершенно непонятно.
S> Зачем кастрировать ООП до уровня интерфейсов?
Для того, чтобы удешевить разработку. Вообще весь дизайн софта — он про удешевление разработки и внесения будущих изменений. Если какая-то концепция не помогает достичь этой цели — грош ей цена, даже если она кажется красивой.
Поэтому ООП надо уметь применять по назначению. В частности, никто вас не ограничивает в построении иерархии классов ВидПартионногоУчёта, которые детализируют поведение нужным образом. А вот пытаться приделать поведение по списанию к иерархии классов документов практической ценности не имеет.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Serginio1, Вы писали:
S>Здравствуйте, Sinclair, Вы писали:
S>Кстати часто нужно добавить свойство метод и в место того, что бы добавить это в базовый класс приходится во всех наследниках добавлять это поле, не забыть в хэлпере его проинициализировать.
Чего?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Serginio1, Вы писали:
S>>Кстати и в 1С стараются применять утинную типизацию. Но это костыли. S>При чём тут утиная типизация?
Интерфейс это по сути и есть та самая утиная типизация. В 1С это двойная диспетчеризация. Где нет ООП S>> Ну вот форма может быть близкой к треугольнику, прямоугольнику, овалу, серпу итд. И соответственно наследоваться от этих фигур. Либо иметь функцию трансформации в такую фигуру. S>Простите, это чушь. "Функция трансформации" определяется не тем, кто от кого отнаследован, а степенью близости к определённой форме. К примеру, овал одной формы будет близок к прямоугольнику, а другой формы — к кругу. Под близостью я понимаю отношение площади фигуры к площади покрывающей её фигуры "упрощённой" формы. Ну так вот в таком подходе совершенно непонятно, от кого наследовать овал — от прямоугольника или от круга. Это показывает ущербность идеи вообще применять наследование для этих целей.
Есть базовый класс с массивом точек по которому можно построить фигуру, На основании их можно построить создать простые формы. Можно для каждой фигуры выбирать близкий по виду. Как правило самый простой алгоритм это прямоугольники. Затем прямоугольники с треугольниками итд. Для обсчета нужны простые фигуры. Фигуры по своей сути не наследуются, но там возможны функции трансформации.
S>> Я уже приводил пример со списанием по партиям. Какое там нарушение логики, если правильно спроектировани базовый класс, а наследники отвечают за дополнительную часть? S>А откуда вы знаете, что наследники корректно отвечают за "дополнительную" часть? Без перетестирования вы этого никак не узнаете.
А тем, что для алгоритма нужно знать только базовые данные от которого зависит первичный алгоритм. Например для списания по ЛИФО нужны те же данные, что и списание по ФИФО.
S>>Другое дело, что документы могут быть смешанными. Например и складскими так и взаиморасчеты с клиентами. И приходится применять разные тактики. Например можно трансформировать в объект другого класса, можно применить интерфейсы итд. S>А можно спроектировать так, чтобы не вносить лишних зависимостей. Трансформировать в объект другого класса нельзя — вы потеряете идентичность. Если у вас зародилась идея поменять класс, сохранив идентичность, то лучше убейте её в зародыше, т.к. она взорвёт всю объектную модель. Вы потеряете типобезопасность — т.е. какие-то ссылки на объект класса А внезапно окажутся ссылками на объект класса Б. В лучшем случае вы получите cast exception в рантайме; в более плохом вы будете применять неподходящие методы. S>Поверьте мне на слово — я норматив на мастера спорта в этом выпиливании лобзиком по вазелину выполнил ещё тогда, когда 1с под стол пешком ходил.
Ну вот пример. Для того, что бы использовать функцию хэлпер, данные должны быть сгруппированы в некую структуру имеющие в том числе и табличные части. Это ничем не отличается от Интерфейса.
Для примера есть контракт который имеет 100 свойств. Мне проще создать объект у которого заполнить только 3 свойства, а остальные заполнить по умолчанию, вместо того, что бы городить интерфейс и реализовывать все 100 свойств. Ничего в типобезопасности я не потеряю. Для примера в NET прекрасно пользуются трансформаторы например IEnumerator IEnumerable.GetEnumerator() который в 99 процентов случаев создает класс оболочку.
Мало того, когда данные применяются только для чтения, то и создание того объекта ничем не отличается от DataSet ов и прочих структур. Просто к классу уже привязаны функции и можно использовать интелиссенс и прочие вкусности. Просто в качестве нужной ссылки будет не this, а другое поле ссылающееся на оригинал.
S>>А кто мешает стратегию применить в базовом классе? Интерфейсы в большинстве случаев более сложный вариант и нет у него преймуществ перед иерархией классов. S>Я вам объяснил уже, почему не применить. Потому что документ не должен решать, какова стратегия партионного учёта. Сегодня она одна, а завтра — другая. Документ при этом остаётся документом.
Тогда я должен это прописать в методе хэлпере. Чем метод хэлпера отличается от классового метода?
S>> То есть ты считаешь что ООП не нужно? S>Я считаю, что большинство программистов неверно понимают ООП — спасибо идиотской пропаганде заблуждений. S>>Да здравствует утинная типизация (интерфейсы это просто типизированный контракт). И мыслить не реальными категориями наследования которые присутствуют в реальной жизни, а городить костыли непонятно зачем. S>В реальной жизни нет категорий наследования, которые поддерживаются в ООП. Вас обманули. S>Те же типы документов построить в дерево крайне тяжело. И да, "утиная типизация" для них подходит лучше, чем многая другая. Грубо говоря потому, что от документа для какого-либо процесса обычно требуется иметь некий набор атрибутов. При этом у одного типа документов могут быть атрибуты А и Б, у другого — Б и В, а у третьего — А и В. И кого от кого тут наследовать — совершенно непонятно.
Есть складские документы. У которых есть свойство склад и табличная часть товары одинаковая состав полей базоваго класса одинаков для всех. Вот и приходится для создания нового документа просто копировать документ только добавляя в него новые. Так что у всех будут поля А,Б,В. А вот другие поля могут быть различными даже при одинаковом названии.
И таких копи пастов в 1С пруд пруди.
Ну и многое решается на уровне виртуальных свойств.
S>> Зачем кастрировать ООП до уровня интерфейсов? S>Для того, чтобы удешевить разработку. Вообще весь дизайн софта — он про удешевление разработки и внесения будущих изменений. Если какая-то концепция не помогает достичь этой цели — грош ей цена, даже если она кажется красивой. S>Поэтому ООП надо уметь применять по назначению. В частности, никто вас не ограничивает в построении иерархии классов ВидПартионногоУчёта, которые детализируют поведение нужным образом. А вот пытаться приделать поведение по списанию к иерархии классов документов практической ценности не имеет.
Это не приделывание. Если ты моделируешь походку для абстрактного класса человек, то она будет так же применена для его наследников женщина и мужчина.
Просто в реальности есть реальные иерархии, а не притянутые за уши. Вот их и нужно разделять как в твоем примере с фигурами.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Serginio1, Вы писали:
S>>Здравствуйте, Sinclair, Вы писали:
S>>Кстати часто нужно добавить свойство метод и в место того, что бы добавить это в базовый класс приходится во всех наследниках добавлять это поле, не забыть в хэлпере его проинициализировать.
S>Чего?
Я уже писал, что для того что бы создать новый документ, я беру близкий к нему просто копирую и добавляю новые поля. Вместо того, что бы отнаследоваться и добавить новое поле.
Если я в базовом классе добавлю поле, то мне без наследования придется добавлять во все классы это поле. Как я это делаю в 1С 8 ке.
и солнце б утром не вставало, когда бы не было меня