Страницы

Поиск по вопросам

вторник, 26 ноября 2019 г.

В чем преимущества однокорневой иерархии классов?


В чем заключаются основные преимущества однокорневой иерархии классов, когда вс
классы наследуются от одного класса, например Object? Что побудило разработчиков языков с однокорневой иерархией классов пойти именно по этому пути?
    


Ответы

Ответ 1



Главным образом для того, чтобы у всех объектов и классов было общее поведение, также поведение по умолчанию, которое содержится в виртуальных методах, которые можно переопределить. Для этого лучше всего походит единый корневой объект. Это гарантирует, что у всех типов будут определённые методы. Для того, чтобы можно было писать члены (методы, свойства, индексаторы, события т.д.), которые могут по-разному работать с абсолютно непохожими типами. Однако эта возможност сильно нивелировалась более удобными Generic и удалила необходимость проверки типов и приведений, ошибки в которых можно было увидеть во время исполнения. Однако по-прежнему существует API (в том числе и стандартное), которое было разработано до Generic, и в котором активно используется корневой тип.

Ответ 2



Не знаю на счет преимуществ, но, как мне кажется, вполне логично иногда (иногда потому что не надо это везде впихивать к месту и не к месту) определить общую часть, котора может быть у классов-наследников. И получается иногда так, что при анализе и построени будущей структуры (иерархии) выходит, что все классы будут иметь какие-то общие поля методы (Естественно процесс выстроения иерархии занимает не день и, порой, даже не месяц. Это надо помнить). Так в C# и Java есть метод toString, который возвращает строковое представление объекта, Finalize — в котором можно описать логику, когда объект уничтожается и другие поля/методы. Не было бы никакого смысла описывать эти методы постоянно в десятках других классах. Это, как минимум, избыточность. Это как-то более естественно, в некоторой аналогии: есть кто считает, что люди произошл от Адама и Евы. А это своего рода та же иерархия и наследование от корня)) Такая иерархи более легка и для понимания: дерево, только растущее сверху вниз, имеющие общие корни, подпитка из одного источника, а не как насаждение кустарников, сорняков-вьюнков, за которыми не видно своего огорода и своих помидорок с огурчиками.

Ответ 3



Множественное наследование дает дополнительную гибкость и возможность повторног использования кода, но порождает ряд проблем, связанных с неоднозначностью, котора возникает, когда у двух или более предков нашего класса есть совпадающие по сигнатур методы. Наиболее известная проблема - т. наз. "проблема ромба", когда мы наследуем одновременн от двух классов (назовем их, к примеру, A и B), являющихся потомками одного и того же общего для них предка, и каждый из наших двух предков по-своему переопределяет метод, определенный в общем предке, скажем int common(int i). Когда код, использующий наш класс, вызовет его метод common(33), какой из методов - A.common() или B.common() - должен выполняться? Разные языки, в которых реализовано множественное наследование, по-разному решаю возникающие проблемы, но в любом случае эти решения приводят к усложнению языка, порой к искусственным ограничениям и т. д. В реальных проектах иерархии используемых классов обычно бывают довольно сложным и запутанными (достаточно посмотреть на стандартные библиотеки классов в любом нормальном языке), и проблемы множественного наследования в этих условиях могут превратиться в немалую головную боль, порождая уйму ошибок, которые бывает нелегко найти и исправить. Кроме того, множественное наследование часто провоцирует программиста на использовани запутанных и неоднозначных решений, способствующих появлению ошибок, в отличие от одиночного наследования, которое, как правило, обеспечивает большую логическую ясность и стройность решений, а значит, снижает вероятность ошибок. Поэтому многие программисты (включая создателей Java) пришли к убеждению, что множественно наследование в чистом виде приносит больше геморроя и головной боли, чем гибкости, и отказались от него. А желаемая гибкость довольно успешно достигается другими средствами - интерфейсами, обобщенными классами и пр. См. https://ru.wikipedia.org/wiki/Ромбовидное_наследование, ну и вообще поискат можно, где об этом пишут - напр. http://www.viva64.com/ru/b/0204/

Ответ 4



Например, в Java используется "простое" (не множественное) наследование, то без единого корня иерархии было бы сложно (не возможно) организовать контейнеры - list, map, etc. Такая организация иерархии была в введена в Smalltalk и многие языки взяли эту идею из него. На мой взгляд подобная организация легче для понимания и уменьшает количество ошибок при разработке.

Ответ 5



Мое imho и не более того - что это в определенной степени замена обобщенного программирования Например, лично мне еще до STL в C++ страшно хотелось написать класс-контейнер тип нынешнего вектора. Это было несложно сделать, для моих целей было сделано - но нужн было указать конкретный тип. В результате вариантов было два - либо для каждого типа заново переписывать код, либо порождать все классы, которые хотелось бы прятать в контейнер, от некоторого общего (при этом оказывались в пролёте фундаментальные типы). Шаблоны достаточно изящно решили эту проблему. Насколько я знаю Java, там изначально пошли по другому пути, и дженерики - это уж возможность совершенно иного времени. Та же (поправьте, если ошибаюсь) даже фундаментальны типы в принципе являются классами. Этакое другое проектное решение, которое обеспечило замену обобщенного программирования в C++, и которое активно используется в самом языке - для того же преобразования, например, в строки.

Комментариев нет:

Отправить комментарий