Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.138.125.2] |
|
Сообщ.
#1
,
|
|
|
Собсно вопрос, который часто возникает при проектировании объектной модели, и который я не до конца понимаю и который я попытался выразить в простом примере - что от чего наследовать: прямоугольник от квадрата или квадрат от прямоугольника?
1) С одной стороны логично наследовать что-то более конкретное от более общего - то есть унаследовать квадрат от прямоугольника, так как любой квадрат является прямоугольником, но не любой прямоугольник квадратом. В этом случае для кода: class Rectangle { } class Square : Rectangle { } Square obj = new Square(); print(obj is Square); // вернет True print(obj is Rectangle); // вернет True 2) С другой стороны, обратное более практично - для прямоугольника необходимо хранить как ширину, так и высоту, в отличии от квадрата для которого достаточно хранить информацию только для одной из сторон. Следовательно при наследовании прямоугольника от квадрата класс Square не будет хранить избыточную информацию, что может быть критично, если нам надо создавать огромный массив объектов. Так как же все таки правильнее наследовать? |
Сообщ.
#2
,
|
|
|
Квадрат от прямоугольника. Но в твоём случае лучше наоборот, т.к. наследование приватное.
P.S. А чё, митинг не помог, что ли? |
Сообщ.
#3
,
|
|
|
Цитата Qraizer @ Квадрат от прямоугольника. Наоборот Прямоугольник от квадрата. Прямоугольник - деформированный квадрат, вводим коэф. деформации - получаем прямоугольник. +k - в ширину, -k - в высоту, ну или наоборот, не суть. Главное не использовать SCRUM! |
Сообщ.
#4
,
|
|
|
Если наследование публичное, то производный класс является ко всему ещё и базовым. Квадрат всегда прямоугольник, но не наоборот.
Если наследование непубличное, то производный класс не более чем связан с базовым какими-либо связями, но им не обязан являться. И в зависимости от рода этих связей наследование может быть использовано для того или иного профита. В частности, для получения в свои руки имеющегося функционала, т.е. для наследования реализации. Всё просто. |
Сообщ.
#5
,
|
|
|
Сообщ.
#6
,
|
|
|
Баянистая троллота. Закапываем.
|
Сообщ.
#7
,
|
|
|
korvin, а ты думаешь, тут не обсуждалось? Мне лень было искать темы. И вообще, темы для холивара тут нет ни разу. Он бы ещё спросил, нужно ли комплексные числа наследовать от вещественных или наоборот, натуральные от целых или как-нибудь иначе, налить сначала сливки в кофе и идти на перекур или наливать после перекура. От скраммера не может быть толковых тем по определению, ибо мозг заточен исключительно под поведенческие паттерны, и никакого творчества.
|
Сообщ.
#8
,
|
|
|
Цитата Qraizer @ а ты думаешь, тут не обсуждалось? Я к тому, что текст стартового поста один в один, т.е. автор скорее всего просто тупо троллит, а не хотя бы хочет что-то обсудить. |
Сообщ.
#9
,
|
|
|
А. Так ты разве не в курсе? Этот автор тут замечен под добрым десятком профилей. Все темы ограничены двумя направлениями. Везде его с трудом хватает только на поддержание скучного разговора. Я был почти уверен, что какой-то школьник оттачивает своего бота для доставания ровесников в ДОТАовом чате, бо стиль общения ни разу не человеческий. Даже ВИ в Mass Effect-е и то обладают лучшими шансами на соответствие тесту Тьюринга. Однако он иногда выходит мне в ПМ, ...и это вызывает сочувствие к его IQ.
|
Сообщ.
#10
,
|
|
|
Цитата Qraizer @ Если наследование публичное, то производный класс является ко всему ещё и базовым. Квадрат всегда прямоугольник, но не наоборот. Если наследование непубличное, то производный класс не более чем связан с базовым какими-либо связями, но им не обязан являться. И в зависимости от рода этих связей наследование может быть использовано для того или иного профита. В частности, для получения в свои руки имеющегося функционала, т.е. для наследования реализации. Всё просто. Давай разберем по косточкам Ну, как я понимаю, главная задача наследования - расширение либо функционала базового класса, либо его характеристик, либо и то и другое? Так, нет? |
Сообщ.
#11
,
|
|
|
Нет. Единственная задача наследования – повторное использование чёрных ящиков с целью сохранить их черноту и создать новую.
|
Сообщ.
#12
,
|
|
|
Цитата JoeUser @ Нихьт. Главная задача наследования - упростить жизнь программисту. Если оно только усложняет, то не надо наследоваться вообще. Полагаю, Qraizer говорит о том же, но с другой стороны. Ну, как я понимаю, главная задача наследования - расширение либо функционала базового класса, либо его характеристик, либо и то и другое? Так, нет? |
Сообщ.
#13
,
|
|
|
Хорошо. Лан. С канонической точки зрения ООП, из трех китов:
Инкапсуляция Полиморфизм Наследование Кто отвечает за расширение функционала? Добавлено Qraizer, хотя твое "нет" ... по сути "да". Создавая новые ящички ты тем самым расширяешь функционал или характеристики. Или я о5 не про то? |
Сообщ.
#14
,
|
|
|
Цитата JoeUser @ Понятно к чемы ты клонишь. Наследование - не обязательно расширяет функционал, а расширение функционала - не обязательно наследование. Это ортогональные понятия. Инкапсуляция Полиморфизм Наследование Кто отвечает за расширение функционала? |
Сообщ.
#15
,
|
|
|
Цитата JoeUser @ Никто.Хорошо. Лан. С канонической точки зрения ООП, из трех китов: Инкапсуляция Полиморфизм Наследование Кто отвечает за расширение функционала? Инкапсуляция - упрощает жизнь программисту тем, что ему не требуется знать что там у объекта внутри - достаточно знать то, что на поверхности. Полиморфизм - упрощает жизнь программисту тем, что позволяет работать с объектами разных связанных между собой типов (класса), как с одним типом, не анализируя тип и не придумывая для каждого типа свой способ обработки (имеется в виду внешняя обработка, внутри класс сам знает, что делать). Ну и при появлении нового класса нет необходимости переписывать под него всю программу. Наследование - упрощает жизнь программисту тем, что позволяет использовать для обработки данных нового типа (класса) процедуры, написанные для базового типа. Ну еще добавлю Перегрузка функций - упрощает жизнь программисту тем, что ему не требуется придумывать и запоминать сложные имена, позволяя использовать простые, легко запоминающиеся, а компилятор сам разберётся какая именно функция имеется в виду. Перегрузка операций - упрощает жизнь программисту тем, что он может использовать естественную запись выражений, а не городить вложенные вызовы функций/процедур. Шаблоны - упрощают жизнь программисту тем, что позволяют один раз описать последовательность действий (функцию, метод, операцию) для типов (классов), обладающих сходными свойствами, а не переписывать её заново для каждого из них. Что-то подобное шаблонам дают дженерики. |
Сообщ.
#16
,
|
|
|
Цитата applegame @ не обязательно Это очень замечательно! Хороший термин. Хуже было бы если бы было "никогда" А теперь давайте рассмотрим две стратегии понятия "построение". В нашем случае есть две стратегии: 1) От меньшего - к большему. Аналог - построение здания из стройматериалов. 2) От большего - к меньшему. Аналог - работа скульптора с камнем. От равного к равному не рассматриваем (типа работа химика или металлурга), ибо, в случае С++, нет функционала замены полей класса при наследовании. Типа в базовом было поле int A, а в наследуемом оно стало Double. Пока рассуждения верны? Добавлено Цитата amk @ Никто. А кто может? Добавлено amk, кстати хорошо, лаконично все описал! Хоть в учебник публикуй! ))) Еще бы описал виртуальное наследование для полноты ... было бы ваще супер. |
Сообщ.
#17
,
|
|
|
Цитата Qraizer @ Однако он иногда выходит мне в ПМ, ...и это вызывает сочувствие к его IQ А в чем смысл этих тем он объяснил? Мне кажется, что тут связка бот + человек. Ну не может сам человек плодить столь бессмысленные темы и причем всегда одинаковые. |
Сообщ.
#18
,
|
|
|
Цитата JoeUser @ Про это, но не с той стороны. Я уж начал в голове повесть сочинять, но вот applegame сказал гораздо талантливее:Или я о5 не про то? Цитата applegame @ Наследование - не обязательно расширяет функционал, а расширение функционала - не обязательно наследование. Это ортогональные понятия. |
Сообщ.
#19
,
|
|
|
Qraizer, с этим разобрались. Идем дашьше.
|
Сообщ.
#20
,
|
|
|
shm, я тоже так думал. Но вот иногда попадаются коты, которым от нечего делать лизать либо нечего, либо не дотянуться. К чужим вот тянутся.
Добавлено Цитата JoeUser @ Лиххко. При наследовании нескольких одинаковых атрибутов требуется решить, следует ли в контексте расширенного функционала рассматривать их как одинаковые или же как разные. К примеру, у окна, поделённого на фреймы, может быть только один атрибут "функция обработки сигналов". А может быть и по одной на каждый фрейм. Это вопрос не программирования, а архитектуры. Как решит проектный менеджер, так и сделает программист (пусть даже это одно лицо). Когда архитектор принимает решение о разделении атрибутов, программист просто использует наследование и не парится, а вот если он решит совместить, тогда программист запарывается на виртуальном наследовании. Еще бы описал виртуальное наследование для полноты ... было бы ваще супер. |
Сообщ.
#21
,
|
|
|
Qraizer, если честно, положа лапу на сердце - вопрос был задан по прочтении этой статьи. Задумался, а нужен ли такой гемор, стОит ли овчинка выделки.
|
Сообщ.
#22
,
|
|
|
И чего все зациклились на квадрате и прямоугольнике? Ведь еще есть ромб и параллелограмм. Которые, вообще-то, частные случаи трапеции. И все это - четырехугольники, частные случаи многоугольников, то есть разновидности замкнутых кривых на плоскости, являющихся множествами точек. Если рассматривать проблему, то в полном объеме!
|
Сообщ.
#23
,
|
|
|
JoeUser, как только я внутри там, почти в самом начале, увидел вектор указателей, читать сразу расхотелось. Но я-таки прочту, позже.
Ну а вообще никто не говорит, что задачи, сводящиеся к множественному наследованию реализаций, просты. |
Сообщ.
#24
,
|
|
|
Начал читать, и снова захотелось бросить, т.к. буквально сразу после кода с вектором указателей наткнулся на банальнейший ляп проектирования: там и речи не идёт о наследовать реализации, задача описана в терминах реализации интерфейсов, и это совершенно другая задача. Если же для JustVisiblePlusUpdate хочется использовать уже готовые, ранее реализованные интерфейсы Renderable и Updatable, то дерево должно быть другим.
В общем, парень хорошо продемонстрировал мой тезис из прошлого поста. Правильная архитектура на первом месте. |
Сообщ.
#25
,
|
|
|
Да у них там ООП головного мозга случился. Неуемное желание создать сложную иерархию ради сложной иерархии. После идиотского мозготраха, они объявили виртуальное наследование богомерзким и переделали дерево.
|
Сообщ.
#26
,
|
|
|
Цитата Qraizer @ Правильная архитектура на первом месте. Именно. И принцип KISS ... Кстати, вот по нему то и ражачная статейка. А по поводу вопросов топика 1) квадрат, окружность, треугольник-равносторонний ... - 1 измерение (половину высоты или радиус) 2) прямоугольник, эллипс, треугольник-равнобедренный ... - 1 измерение + 1 деформация 3) параллелограмм, яйцеобразная форма, треугольник-произвольный ... - 1 измерение + 2 деформации А может вааще сперва изменить систему координат на какую нить эллиптическую |
Сообщ.
#27
,
|
|
|
Сообщ.
#28
,
|
|
|
В природной естественной среде объект принадлежит сразу нескольким классам.
На вопрос по прошу не отвлекаться. Так вот один и тот же предмет можно классифицировать по форме, по цвету, по наличию каёмки и тп. Ещё разные классы могу перекрываться. Отсюда проявляется проблема классификации. Наиболее простой вид классификации. Это когда один класс целиком входи в другой. Наследование с сужением функционала лучше всего работает. Можно заменять реализацию функционала. Но интерфейс будет остаться. А вот наоборот не работает или работает плохо. Так как нельзя вызвать из предка неизвестный функционал потомка. Поэтому предок должен содержать все методы потомков. Но есть и второй способ наследования через перепоручение (Deligate). Что частично решает проблему множественного наследования. В этом случае проблемы перекладываются с интереса на функции где надо обрабатывать через ветвления все варианты работы. Т.е использовать Case. Предок не обязан знать о потомке. И проблему можно решить через внедрение или хук функции. Что усложняет написания кода. При работе с ООП есть методика сокрытия информации. Когда работаешь с объектами она учит программистов пользоваться объектами используя интуиции. Но вот когда встаёт задача проектировать класс то тут уже надо пользоваться другим подходом. А именно абстрагирование. Суть абстрогирование это изучение существующих классов и выбор того набора методов который наилучшим способом описывает все имеющиеся объекты и их реализации данного класса.Другими словами наиболее популярные методы. Для этого надо рассмотреть все классы и возможные реализации. Вот как это делают на примере касса окна в книге 4-тырёх: Цитата Класс Window должен покрывать функциональность окон, которая имеется в различных оконных системах. Рассмотрим два крайних подхода: - пересечение функциональности. Интерфейс класса Window предоставляет только операции, общие для всех оконных систем. Однако в результате мы получаем интерфейс не богаче, чем в самой слабой из рассматриваемых систем. Мы не можем воспользоваться более развитыми средствами, даже если их поддерживает большинство оконных систем (но не все); - объединение функциональности. Создается интерфейс, который включает возможности всех существующих систем. Здесь нас подстерегает опасность получить чрезмерно громоздкий и внутренне не согласованный интерфейс. Кроме того, нам придется изменять его (а вместе с ним и Lexi) всякий раз, как только производитель переработает интерфейс своей оконной системы. Ни то, ни другое решение «в чистом виде» не годятся, поэтому мы выберем компромиссное. Класс Window будет предоставлять удобный интерфейс, поддерживающий наиболее популярные возможности оконных систем. Поскольку редактор Lexi будет работать с классом Window напрямую, этот класс должен поддерживать и сущности, о которых Lexi известно, то есть глифы. Это означает, что интерфейс класса Window должен включать базовый набор графических операций, позволяющий глифам отображать себя в окне. В табл. 2.3 перечислены некоторые операции из интерфейса класса Window. Для прямоугольника и квадрата. Надо смотреть для чего нужно объединять эти два объекта в класс/классы возможно их и не надо объединять вовсе. Но если нужно, то Я бы использовал 3-тий вид наследования. Через множественное наследование интерфейсов. С одной стороны это будет объединение, но с другой стороны и разделения на интерфейсы. |
Сообщ.
#29
,
|
|
|
Цитата Pavia @ На вопрос по прошу не отвлекаться. А я всё-таки отвлекусь Лишняя фигура - первая. Она единственная, которая не имеет признака, отличающего её от остальных четырёх |