Форум: "Прочее";
Текущий архив: 2010.08.27;
Скачать: [xml.tar.bz2];
Вниз[ООП] Хочу странного Найти похожие ветки
← →
Некто (2010-03-08 13:27) [0]При спорах вида "С++ vs X", где Х - любой объектно-ориентированный ЯП, поддерживающий единичное наследование, неизбежно возникает ответвление спора на тему "множественное наследование vs. единичное наследование". Защитники МН упирают на бОльшую гибкость и возможности, которые дает МН, противники - на то, что МН усложняет реализацию языка, сам язык и что МН вообще не нужно.
Мое личное мнение состоит в том, что если рассматривать классическое ООП в стиле Smalltalk, то правы оппоненты МН. Если же рассматривать ООП и как инструмент создания архитектурного каркаса ПО, то я выступаю за МН, ибо он дает хорошие возможности по комбинации функциональности, в частности реализуя возможность mixin-style.
Теперь, собственно, к странному. А надо ли вообще в языке иметь наследование реализации в том виде, в котором это сделано в том же C++/C#/Deplhi/Java т.д.? Что в этих языках имеется в виду, когда говорится "Класс Б наследует класс А"? Имеется в виду две вещи:
1. Класс Б является подтипом А, т.е. поддерживает интерфейс класса А, и является легальным для применения везде, где можно применять А. Это Liskov substitution principle (http://en.wikipedia.org/wiki/Liskov_substitution_principle).
2. Класс Б наследует всю реализацию класса А, его поля и методы, т.е. повторно использует реализацию класса А.
Другими словами, в таком наследовании мы имеем смешение двух идей:
1. Абстракция через обобщение.
2. Повторное использование кода.
Что если принципиально разделить эти вещи? Абстракция через обобщение в чистом виде есть во многих языка в виде интерфейсов, которые, кстати, поддерживают множественное наследование даже там, где классы поддерживают только единичное. Повторное использование кода тоже возможно другим способом - через композицию объектов. Единственное, чего нет - это синтаксически хорошо оформленное делегирование реализации интерфейса/части интерфейса композитам, из которых составлен класс-композиция. Но это не сложный аспект, который можно реализовать.
Данный подход не имеет тех недостатков МН, на которые упирают его противники и в то же время он обеспечивает все его возможности + кое-что сверху. Ваши мнения, коллеги?
← →
Alkid © (2010-03-08 13:28) [1]Тьфу, стартовый пост от моего имени :)
← →
Kerk © (2010-03-08 13:31) [2]Честно говоря, я не понял вопрос.
Лучше ли композиция объектов плюс множественное наследование интерфейсов, чем просто множественное наследование классов?
← →
Piter © (2010-03-08 13:34) [3]мое мнение, что в дельфи сделано оптимально. Она не имеет множественного наследования, но имеет множественное наследование интерфейсов.
← →
Piter © (2010-03-08 13:35) [4]а вопрос действительно непонятный. Alkid ушел куда-то совсем в дебри философии. Сам ведь сказал что "МН vs АнтиМН" не могут договориться, а тут то вообще тема высоких материй затрагивается
← →
Anatoly Podgoretsky © (2010-03-08 13:35) [5]А нам татарам все равно.
← →
Alkid © (2010-03-08 13:48) [6]Я имел в виду следующее: наследование классов как таковое не нужно. Нужна композиция и делегирование. Собственно тогда вопрос "МН vs. ЕН" снимается само собой за упразднением наследования :)
← →
Игорь Шевченко © (2010-03-08 13:51) [7]Есть множественное наследование интерфейса и множественное наследование реализации. Хорошо и то, и другое.
Тут вроде все написано:
http://ru.wikipedia.org/wiki/%D0%9C%D0%BD%D0%BE%D0%B6%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D0%B5_%D0%BD%D0%B0%D1%81%D0%BB%D0%B5%D0%B4%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5
и тут:
http://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%82%D0%B5%D1%80%D1%84%D0%B5%D0%B9%D1%81_(%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%BD%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)
> Другими словами, в таком наследовании мы имеем смешение
> двух идей:
> 1. Абстракция через обобщение.
> 2. Повторное использование кода.
Имеем смешение одной идеи - наследование :)
← →
Kerk © (2010-03-08 13:52) [8]
> Alkid © (08.03.10 13:48) [6]
Наследование еще нужно и для типизации ведь.
← →
Alkid © (2010-03-08 13:59) [9]
> Piter © (08.03.10 13:34) [3]
Да вот не оптимально. Приведу пример из практики. Там C#, но в нем возможности те же. Так вот, есть интерфейс во фреймворке стандартный интерфейс INotifyPropertyChanged, который объявляет событие, уведомляющее подписчиков об изменении свойства объекта. Есть разные реализации этого интерфейса, опирающиеся на разные механизмы (Linq, Reflection). Предположим, что класс называется MyNotifyPropertyChanged.
Далее, есть класс:
public class MyBusinessClass : MyBusinessClassBase, INotifyPropertyChanged
{
...
}
Вопрос: как мне "подмешать" в свой класс реализацию MyNotifyPropertyChanged, что бы он заимплементил INotifyPropertyChanged? В терминах С++ это решается так:
class MyBusinessClass : public MyBuinessClassBase, public virtual INotifyPropertyChanged, private virtual MyNotifyPropertyChanged
{
...
};
← →
Alkid © (2010-03-08 14:02) [10]
> Kerk © (08.03.10 13:52) [8]
> Наследование еще нужно и для типизации ведь.
Это наследование интерфейса. Его я не предлагаю упразднять :)
← →
Alkid © (2010-03-08 14:11) [11]
> Игорь Шевченко © (08.03.10 13:51) [7]
> Есть множественное наследование интерфейса и множественное
> наследование реализации. Хорошо и то, и другое.
Но при этом множественное наследование имеет свои сложности, которые хорошо бы ликвидировать.
> Имеем смешение одной идеи - наследование :)
Со своими недостатками :)
Напримр, почему в Дельфи при наследовании класса я обязан получать подтип, даже если я хочу только его реализацию? Потому что наследование только открытое :) Я не могу унаследовать только реализацию, "интерфейс" идет "в нагрузку".
← →
sniknik © (2010-03-08 14:12) [12]> В терминах С++ это решается так:
а в реальной жизни это бывает нужно?
почему интересуюсь, у нас 2 "чистых" сишника, и оба против использования множественного наследования (обсуждали как то), в смысле "лучше не использовать чтобы не путать логику программы" и в итоге результат как с "goto" вроде бы можно, но реально за всю рабочую деятельность обоим не пригодилось... (мне в дельфи отсутствие тоже в общем то не мешало, и не хотелось, типа "вот эту задачу(реальную) без множественного решить сложно")
в общем встречный вопрос, а есть ли смысл в теоретизировании?
← →
Alkid © (2010-03-08 14:17) [13]
> sniknik © (08.03.10 14:12) [12]
Я же сказал - это пример из практики. Я уперся в ограниченность C#, обрабатывая эту ситуацию. Я пошел под одному пути - включил нужную функциональность в самый базовый класс и ее получили все наследники, даже те, которым она заведомо не нужна. Это было неоптимальное решение, вызванное отсутствием возможностей языка. Так что это не "теоретизирование", а осмысление шишек, набитых на практике.
Что же касается "чистых сишников", то я не удивлюсь - на С нету наследования вообще :)
← →
Игорь Шевченко © (2010-03-08 14:37) [14]Alkid © (08.03.10 14:11) [11]
> Но при этом множественное наследование имеет свои сложности,
> которые хорошо бы ликвидировать.
Ровно одну сложность, описанную по первой ссылке. Ну так "не делать так".
> Напримр, почему в Дельфи при наследовании класса я обязан
> получать подтип, даже если я хочу только его реализацию?
> Потому что наследование только открытое :) Я не могу унаследовать
> только реализацию, "интерфейс" идет "в нагрузку".
Классические пуристы возражают против наследников, например, от TList. Их аргументы таковы, что наследнику в большинстве случаев не нужны методы предка Exchange, Move, и т.д.
Нету в Delphi возможность понизить область видимости - ну такой язык. Зато есть возможность ее повысить, что довольно регулярно используется.
← →
Anatoly Podgoretsky © (2010-03-08 14:41) [15]В жизни дети не выбирают, что наследовать от родителей.
Так пуристы перестреляют половину населения, что бы не противоречило их взлядам на наследование.
← →
Alkid © (2010-03-08 15:09) [16]
> Игорь Шевченко © (08.03.10 14:37) [14]
> Ровно одну сложность, описанную по первой ссылке. Ну так
> "не делать так".
Там несколько проблем перечислено, какую из них ты имеешь в виду?
> Классические пуристы возражают против наследников, например,
> от TList. Их аргументы таковы, что наследнику в большинстве
> случаев не нужны методы предка Exchange, Move, и т.д.
Правильно, они рекомендуют повторно использовать эти классы через композицию.
← →
Игорь Шевченко © (2010-03-08 15:15) [17]Alkid © (08.03.10 15:09) [16]
Увидел одну, "проблему алмаза"
> Правильно, они рекомендуют повторно использовать эти классы
> через композицию.
Писать больше. А чем больше код, тем он более подвержен ошибкам, труднее в восприятии и в тестировании.
Поэтому иногда заветам пуристов можно и не следовать.
Оно же, ООП для чего вообще появилось на свет - чтобы сложность уменьшить. Вот и давайте уменьшать :)
← →
имя (2010-03-08 19:03) [18]Удалено модератором
← →
Некто (2010-03-08 19:03) [19]
> Игорь Шевченко © (08.03.10 15:15) [17]
> Увидел одну, "проблему алмаза"
Ну есть и другие. Например, способ разрешения совпадающих имен.
> Писать больше. А чем больше код, тем он более подвержен
> ошибкам, труднее в восприятии и в тестировании
Написанный и покрытый юнит-тестам код сам по себе проблемы не будет представлять, даже если он будет больше альтернативного. С другой стороны, если он раз и навсегда закроет "дыры", вылезающие из-за нежелательного раскрытия интерфейса TList, то он в корне устранит возможные ошибки, вызванные неправильными его использованием из других мест в программе. Эти ошибки опаснее.
> Поэтому иногда заветам пуристов можно и не следовать.
Я бы ЭТО пуризмом не назвал :)
> Оно же, ООП для чего вообще появилось на свет - чтобы сложность
> уменьшить. Вот и давайте уменьшать :)
Так этим и занимаюсь! :)
← →
Игорь Шевченко © (2010-03-08 19:37) [20]Некто (08.03.10 19:03) [19]
> Написанный и покрытый юнит-тестам код сам по себе проблемы
> не будет представлять, даже если он будет больше альтернативного.
> С другой стороны, если он раз и навсегда закроет "дыры",
> вылезающие из-за нежелательного раскрытия интерфейса TList,
> то он в корне устранит возможные ошибки, вызванные неправильными
> его использованием из других мест в программе. Эти ошибки
> опаснее.
Все пуристы так говорят. Только при этом они считают, что необходмость написания и восприятия написанного кода совершенно ничего не стоит - ну подумаешь, написали пару десятков классов, написали сотню юнит-тестов, а потом со всем этим зоопарком разбираться не нам, а пользователям.
Мне иногда проще написать наследников, оставляя потенциально лишнюю функциональность, чем выполнять композицию. Я надеюсь, Аллах в это время отвернется :)
Это с одной стороны.
С другой стороны не так давно видел хорошее высказывание
"I"ve always been an advocate of the school that says "write more code when preparing an infrastructure so you can write less code when using this infrastructure""
найти бы компромисс :)
← →
vuk © (2010-03-08 19:48) [21]to Игорь Шевченко © (08.03.10 15:15) [17]:
> Оно же, ООП для чего вообще появилось на свет - чтобы сложность
> уменьшить.
Немного не так, наверное. Не для того, чтобы уменьшить, а для того, чтобы со сложностью сосуществовать. На самом деле структуры, которые реализуются в ООП, они не проще, а, как правило, сложнее. Просто ООП дает возможность сложные вещи структурировать и бороться со сложностью "по частям". Всё IMHO.
← →
cwl © (2010-03-08 19:49) [22]> Игорь Шевченко © (08.03.10 19:37) [20]
"I"ve always been an advocate of the school that says "write more code when preparing an infrastructure so you can write less code when using this infrastructure""
часто цитируемый вами МакКоннел в начале книги и пишет про расширяемость - в чем же проблема :>
// или это он и есть в английском варианте
← →
Игорь Шевченко © (2010-03-08 20:12) [23]cwl © (08.03.10 19:49) [22]
> или это он и есть в английском варианте
Нет, это не он, это из комментариев к
http://17slon.com/blogs/gabr/2007/03/fun-with-enumerators-part-3.html
кстати, хороший блог по Delphi
vuk © (08.03.10 19:48) [21]
"Когда в середине 1980-х годов С++ впервые был выпущен в свет, объектно-ориентированные языки программирования были широко разрекламированы как радикальное средство борьбы против сложности программного обеспечения".
Эрик Реймонд, "Искусство программирования для Unix"
Буч в своем бестселлере примерно о том же пишет, только менее радикально :)
← →
vuk © (2010-03-08 20:17) [24]to Игорь Шевченко © (08.03.10 20:12) [23]:
Вот с борьбой со сложностью согласен. Но борьба со сложностью не равна упрощению. Как-то так.
← →
Игорь Шевченко © (2010-03-08 20:21) [25]vuk © (08.03.10 20:17) [24]
ООП уменьшает сложность реализации и сложность проектирования, но не сложность самой системы, наверное так будет правильно.
← →
vuk © (2010-03-08 20:43) [26]to Игорь Шевченко © (08.03.10 20:21) [25]:
> ООП уменьшает сложность реализации и сложность проектирования,
> но не сложность самой системы, наверное так будет правильно.
>
Именно.
← →
oxffff © (2010-03-08 21:16) [27]
> Alkid © (08.03.10 13:59) [9]
>
> > Piter © (08.03.10 13:34) [3]
>
> Да вот не оптимально. Приведу пример из практики. Там C#,
> но в нем возможности те же. Так вот, есть интерфейс во
> фреймворке стандартный интерфейс INotifyPropertyChanged,
> который объявляет событие, уведомляющее подписчиков об
> изменении свойства объекта. Есть разные реализации этого
> интерфейса, опирающиеся на разные механизмы (Linq, Reflection).
> Предположим, что класс называется MyNotifyPropertyChanged.
>
>
> Далее, есть класс:
>
> public class MyBusinessClass : MyBusinessClassBase, INotifyPropertyChanged
> {
> ...
> }
>
> Вопрос: как мне "подмешать" в свой класс реализацию MyNotifyPropertyChanged,
> что бы он заимплементил INotifyPropertyChanged? В терминах
> С++ это решается так:
>
> class MyBusinessClass : public MyBuinessClassBase, public
> virtual INotifyPropertyChanged, private virtual MyNotifyPropertyChanged
> {
> ...
> };
В Delphi есть делегирование реализации implements, если я правильно понял вопрос.
В остальном я скоро приеду и у нас будет возможность посидеть и обсудить это. :)
← →
oxffff © (2010-03-08 21:34) [28]
> Игорь Шевченко © (08.03.10 14:37) [14]
> Alkid © (08.03.10 14:11) [11]
> Нету в Delphi возможность понизить область видимости - ну
> такой язык. Зато есть возможность ее повысить, что довольно
> регулярно используется.
Этой возможности быть и не должно. :)
Поскольку, если B является подклассом A, то B является подтипом A.
Если позволить менять видимость, то тогда B не будет являться подтипом A.
Поскольку B не может выступить в качестве А
(нарушение типобезопасности, то есть язык будет являться небезопасным)
← →
Игорь Шевченко © (2010-03-08 22:03) [29]oxffff © (08.03.10 21:34) [28]
То же самое, только по-русски можно ?
← →
oxffff © (2010-03-08 22:22) [30]
> Игорь Шевченко © (08.03.10 22:03) [29]
> oxffff © (08.03.10 21:34) [28]
>
> То же самое, только по-русски можно ?
:)
Например
A=class
public
InstanceFieldA:integer;
end;
B=class(A)
change ability to private
InstanceFieldA;
end;
И есть функция Foo(obj:A). То в эту функцию передать экземпляр B нельзя поскольку B не может вести себя как A(то есть быть подтипом). Поскольку предполагается что функция принимает нечно у которого есть открытый доступ к InstanceFieldA. Мы не можем передать в функцию B, поскольку открытого доступа к InstanceFieldA нет. То есть хотя B является подклассом, B не является подтипом, в противном случае будет нарушение инкапсуляции, поскольку будет раскрыт доступ к закрытой части.
← →
jack128_ (2010-03-08 22:40) [31]
> То же самое, только по-русски можно ?
Принцип Лисковой вроде это -)
← →
Alkid © (2010-03-08 22:45) [32]
> oxffff © (08.03.10 21:34) [28]
Не пугай меня. Есть С++ с закрытым наследованием. Так что ты можешь мне написать пример, иллюстрирующий нетипобезопасность закрытого наследования :)
← →
Alkid © (2010-03-08 22:51) [33]
> oxffff © (08.03.10 22:22) [30]
В общем, подкласс и подтип - это в общем случае не синонимичные понятия. В языках типа Дельфи, C#, Java - это так, но в С++ уже не так и можно совершенно легально порождать подклассы, не подчиняющиеся LSP.
← →
Игорь Шевченко © (2010-03-08 23:09) [34]Alkid © (08.03.10 22:45) [32]
Опередил :)
Дети обязательно должны наследовать реализацию родителей, и не обязательно должны наследовать их интерфейс.
Что, собственно и в жизни наблюдается :)
← →
oxffff © (2010-03-08 23:13) [35]
> Alkid © (08.03.10 22:45) [32]
>
> > oxffff © (08.03.10 21:34) [28]
>
> Не пугай меня. Есть С++ с закрытым наследованием. Так что
> ты можешь мне написать пример, иллюстрирующий нетипобезопасность
> закрытого наследования :)
Ты можешь сам написать такой пример ориентируясь на [30].
← →
oxffff © (2010-03-08 23:16) [36]
> Alkid © (08.03.10 22:51) [33]
>
> > oxffff © (08.03.10 22:22) [30]
>
> В общем, подкласс и подтип - это в общем случае не синонимичные
> понятия. В языках типа Дельфи, C#, Java - это так, но в
> С++ уже не так и можно совершенно легально порождать подклассы,
> не подчиняющиеся LSP.
Вообще нужно говорить наверно о теории типов, а не о LSP.
Так вот, то что положено в С++ это решение автора со всеми вытекающими.
Так же как и в JAVA знаменитая проблема с подтипами массивов.
← →
oxffff © (2010-03-08 23:20) [37]
> Игорь Шевченко © (08.03.10 23:09) [34]
> Alkid © (08.03.10 22:45) [32]
>
> Опередил :)
>
> Дети обязательно должны наследовать реализацию родителей,
> и не обязательно должны наследовать их интерфейс.
>
> Что, собственно и в жизни наблюдается :)
Это в жизни так, поскольку отношение подтипа отличное.
Формально в теории типов другие правила, а попытка заместить неизвестное "похожим" можно сильно ударить в будущем.
Есть формальная теория рекомендую к ней обратиться.
← →
Игорь Шевченко © (2010-03-08 23:29) [38]oxffff © (08.03.10 23:20) [37]
> Есть формальная теория рекомендую к ней обратиться.
Есть синтаксис конкретных языков. Можно я буду к нему обращаться ? :)
← →
oxffff © (2010-03-08 23:30) [39]Вот кратко
There is one kind of change that can be made to methods in subclasses that
we have not yet considered. Rather than changing the types of methods, we
can consider changing the visibility of methods.
We have not discussed this earlier because our defaults have been that all
methods are visible. We will continue with those defaults until section 14.4,
but sincemost object-oriented languages do allowthe programmer to specify
degrees of information hiding, we briefly address this question in terms of
preserving safety in subclasses.
It is easy to see that taking methods that are hidden inside superclasses
and making them more visible in subclasses causes no problems with inherited
methods or even in having subclasses generate subtypes. What is more
interesting is that, if we do not care whether subclasses generate subtypes,
we can also make methods less visible in subclasses.
Выделенное говорит о том, что если B является подклассом A, но не является подтипом А мы не может передать B в функцию которая ожидает A.
Если это допустить, то будет нарушение типов.
Читайте теорию господа.
← →
oxffff © (2010-03-08 23:31) [40]
> Игорь Шевченко © (08.03.10 23:29) [38]
> oxffff © (08.03.10 23:20) [37]
>
>
> > Есть формальная теория рекомендую к ней обратиться.
>
>
> Есть синтаксис конкретных языков. Можно я буду к нему обращаться
> ? :)
Ради бога. Есть теория можно я буду к ней обращаться?
← →
Игорь Шевченко © (2010-03-08 23:33) [41]oxffff © (08.03.10 23:31) [40]
> Есть теория можно я буду к ней обращаться?
Ради бога. Только ты пиши, когда к теории обращаешься, чтобы было понятно, договорились ?
← →
oxffff © (2010-03-08 23:36) [42]
> Игорь Шевченко © (08.03.10 23:33) [41]
> oxffff © (08.03.10 23:31) [40]
>
>
> > Есть теория можно я буду к ней обращаться?
>
>
> Ради бога. Только ты пиши, когда к теории обращаешься, чтобы
> было понятно, договорились ?
Договорились. И?
← →
oxffff © (2010-03-08 23:40) [43]Еще немного теории
Of course, if one hides a previously public method, m, in a subclass SC of
C, then SC no longer generates objects whose type is a subtype of the objects
generated by C. Objects generated from C can respond to message m, while
those generated from SC cannot.
← →
Alkid © (2010-03-09 00:00) [44]
> oxffff © (08.03.10 23:16) [36]
> Вообще нужно говорить наверно о теории типов, а не о LSP.
>
> Так вот, то что положено в С++ это решение автора со всеми
> вытекающими.
И с какими же вытекающими? Возможность порождать подкласс, не являющийся подтипом, не противоречит абсолютно ничему. Закрытое наследование, по сути, является разновидностью композиции.
В С++ это выдерживается строго, ты не можешь приводить класс к закрытому базовому классу без применения тяжелой артиллерии в виде reinterpret_cast или C-style cast.
Так же как и в JAVA знаменитая проблема с подтипами массивов.
Можно поподробнее? Я не знаток Java, так что не в курсе проблемы.
> Читайте теорию господа.
Теория - это хорошо, но она пока не объясняет, в чем же ты усмотрел "нетипобезопасность" и прочий криминал. Нетипобезопасность, по моему пониманию, это когда ты присваиваешь переменной значение нелегального типа. Ну, есть у тебя указатель на Foo, а ты тыкаешь его в экземпляр Bar. Тогда у тебя будут все радости, типа AV, порчи памяти и так далее.
← →
Alkid © (2010-03-09 00:06) [45]
> oxffff © (08.03.10 21:16) [27]
> В Delphi есть делегирование реализации implements, если
> я правильно понял вопрос.
> В остальном я скоро приеду и у нас будет возможность посидеть
> и обсудить это. :)
Да, ты правильно понял вопрос.
А я, видимо, стал забывать Дельфи уже :)
← →
oxffff © (2010-03-09 00:22) [46]
> Alkid © (09.03.10 00:00) [44]
>
> > oxffff © (08.03.10 23:16) [36]
> > Вообще нужно говорить наверно о теории типов, а не о LSP.
>
> >
> > Так вот, то что положено в С++ это решение автора со всеми
>
> > вытекающими.
>
> И с какими же вытекающими? Возможность порождать подкласс,
> не являющийся подтипом, не противоречит абсолютно ничему.
> Закрытое наследование, по сути, является разновидностью
> композиции.
>
> В С++ это выдерживается строго, ты не можешь приводить класс
> к закрытому базовому классу без применения тяжелой артиллерии
> в виде reinterpret_cast или C-style cast.
>
Применение тяжелой артилерии(а значит и передача ответственности программисту) означает, что компилятор(среда) не может гарантировать безопасность программы самостоятельно, а это в свою очередь означает не 100% безопасность типов.
Поэтому жесткое приведение тут же как бы намекает на вопрос, а правильно ли программист спроектировал классы и отношения подтипов. И нужна ли такая возможность в языке, если она может порождать проблемы. И возможно этого можно добиться "не расширяя(засоряя)" язык посредством примитивных базовых конструкций.
>
> Так же как и в JAVA знаменитая проблема с подтипами массивов.
>
>
> Можно поподробнее? Я не знаток Java, так что не в курсе
> проблемы.
>
>
JAVA правило для массивов.
B[] является подтипом A[], если B является подтипом A.
Что приводит к тому, что в массив фруктов можно добавить овощи.
> > Читайте теорию господа.
>
> Теория - это хорошо, но она пока не объясняет, в чем же
> ты усмотрел "нетипобезопасность" и прочий криминал. Нетипобезопасность,
> по моему пониманию, это когда ты присваиваешь переменной
> значение нелегального типа. Ну, есть у тебя указатель на
> Foo, а ты тыкаешь его в экземпляр Bar. Тогда у тебя будут
> все радости, типа AV, порчи памяти и так далее.
см. выше+
Every value generated in a program is associatedwith a type, either explicitly
or implicitly. In a strongly typed language, the language implementation
is required to provide a type checker that ensures that no type errors will occur
at run time.
← →
Игорь Шевченко © (2010-03-09 00:25) [47]oxffff © (09.03.10 00:22) [46]
> Every value generated in a program is associatedwith a type,
> either explicitly
> or implicitly. In a strongly typed language, the language
> implementation
> is required to provide a type checker that ensures that
> no type errors will occur
> at run time.
Если тебя не затруднит, ты по-русски сразу пиши, а ?
Задолбало уже.
← →
oxffff © (2010-03-09 00:32) [48]
> Игорь Шевченко © (09.03.10 00:25) [47]
> oxffff © (09.03.10 00:22) [46]
>
>
> > Every value generated in a program is associatedwith a
> type,
> > either explicitly
> > or implicitly. In a strongly typed language, the language
>
> > implementation
> > is required to provide a type checker that ensures that
>
> > no type errors will occur
> > at run time.
>
>
> Если тебя не затруднит, ты по-русски сразу пиши, а ?
> Задолбало уже.
Все я спать пошел. :)
← →
Германн © (2010-03-09 00:44) [49]
> Игорь Шевченко © (09.03.10 00:25) [47]
Вроде нет проблем с переводом. Всё с первого взгляда понятно.
Или я "не в теме"?
← →
Alkid © (2010-03-09 09:53) [50]
> oxffff © (09.03.10 00:22) [46]
> Применение тяжелой артилерии(а значит и передача ответственности
> программисту) означает, что компилятор(среда) не может гарантировать
> безопасность программы самостоятельно, а это в свою очередь
> означает не 100% безопасность типов.
Безусловно. Собственно, эти типы приведения нужны *только* для низкоуровневой работы с памятью. За создание закрытого наследования и приведения его потом к приватной базе через reinterpret_cast надо расстреливать через повешение. При нормальном проектировании такого быть не должно, что не отменяет допустимость закрытого наследования.
> Every value generated in a program is associatedwith a type,
> either explicitly
> or implicitly. In a strongly typed language, the language
> implementation
> is required to provide a type checker that ensures that
> no type errors will occur
> at run time.
Ну вот и поясни мне, как закрытое наследование порождает "error at run time", а то я пока не понимаю этого.
← →
oxffff © (2010-03-09 10:11) [51]
> Ну вот и поясни мне, как закрытое наследование порождает
> "error at run time", а то я пока не понимаю этого.
Очень просто. Есть класс B, который наследует приватно от А, скрывая интерфейс А, и выставляя некий свой другой. Что означает, что изменение значений закрытой части в B, контролирует B, но не внешнее окружение. А это в свою очередь означает, что эти закрытые члены могут принимать некие определенные значения(их домен значений в B, например подмножество всех допустимых значений в А), а также все отношения между этимим полями должны быть определенными и могут иметь предназначение отличное от их предназначения в А. Поэтому если B трактовать как A(отношение подтипа), по мы нарушает абстракцию B, Что могут вызвать ошибки времени исполнения, в случае если значения вышли из домена значений допустимых в B(например индекс в неком расделенном массиве). Надеюсь я понятно объяснил. :)
← →
oxffff © (2010-03-09 10:14) [52]
> Поэтому если B трактовать как A(отношение подтипа), по
> мы нарушает абстракцию B, Что могут вызвать ошибки времени
> исполнения, в случае если значения вышли из домена значений
> допустимых в B(например индекс в неком расделенном массиве).
> Надеюсь я понятно объяснил. :)
например для А допустимы индексы от 1 до 100.
Для B допустимы индексы от 5 до 87.
Значение индекса вне [5,87] будет некорректным в B, что приведет к ошибке в его работе и значит и ошибки Run-time. :)
← →
Alkid © (2010-03-09 10:46) [53]
> oxffff © (09.03.10 10:11) [51]
> oxffff © (09.03.10 10:14) [52]
Не, я не понял, что ты имеешь в виду. Закрытое наследование не порождаем подтипа. Т.е.:
class A { };
class B : private A {};
...
A* a = new B(); // Ошибка компиляции!
Это означает, что ты не можешь передать B туда, где применим А, принцип подстановки не работает. Пользователь класса B не знает о том, что тот унаследован от A, это является исключительно деталью реализации.
В общем, жду примера, в котором без применения всяких дурных кастов ты получишь нетипобезопасную программу. Т.е. компилирующуюся, но падающую в run-time от ошибки типов.
← →
jack128_ (2010-03-09 10:52) [54]
> Некто (08.03.10 13:27)
тут обсуждение в какие то непнятные теоретические дебри и особенности cpp, давайте ближе к телу вопроса.
мя в предложенной схеме смущают два момента:
1) весь публичный интерфейс - полиморфный.
2) отсутствие protected (в виду отсутствия наследования классов)
в качестве примера шаблонный метод реализуем:
TBase = class
protected
procedure DoStep1(); virtual;
procedure DoStep2(); virtual;
procedure DoStep3(); virtual;
public
procedure DoWork(); // вызывает последовательно DoStep1/DoStep2/DoStep3
end;
TChild1 = class(TBase)
protected
procedure DoStep1(); override;
procedure DoStep2(); override;
procedure DoStep3(); override;
end;
TChild2 = class(TBase)
protected
procedure DoStep1(); override;
procedure DoStep2(); override;
procedure DoStep3(); override;
end;
по твоей схеме эту иерархию мона преобразовать так:
IBase = interface
procedure DoStep1();
procedure DoStep2();
procedure DoStep3();
end;
procedure DoWork(base: IBase);
begin
base.DoStep1();
base.DoStep2();
base.DoStep3();
end;
но тогда отдельные шаги передут в публичный интерфейс и станут доступны каждому встречному поперечному.
либо просто объявить
IWorker = interface
procedure DoWork();
end
но тогда теряется шаблонность. Как быть??
← →
oxffff © (2010-03-09 10:55) [55]
> Alkid © (09.03.10 10:46) [53]
>
> > oxffff © (09.03.10 10:11) [51]
> > oxffff © (09.03.10 10:14) [52]
>
> Не, я не понял, что ты имеешь в виду. Закрытое наследование
> не порождаем подтипа. Т.е.:
>
> class A { };
> class B : private A {};
> ...
> A* a = new B(); // Ошибка компиляции!
>
> Это означает, что ты не можешь передать B туда, где применим
> А, принцип подстановки не работает. Пользователь класса
> B не знает о том, что тот унаследован от A, это является
> исключительно деталью реализации.
>
> В общем, жду примера, в котором без применения всяких дурных
> кастов ты получишь нетипобезопасную программу. Т.е. компилирующуюся,
> но падающую в run-time от ошибки типов.
Ты определись что ты хочешь?
Я написал что применение закрытого наследования при сохранении отношений подтипа для подклассов или использования cast"ов является небезопасным.
← →
Alkid © (2010-03-09 11:06) [56]
> oxffff © (09.03.10 10:55) [55]
А я писал, что подтип и подкласс - не синонимы, что допустимо порождать подкласс, не являющийся подтипом, и что за касты расстреливать надо на месте :)
Смотри [44], откуда все началось.
← →
Alkid © (2010-03-09 11:09) [57]
> jack128_ (09.03.10 10:52) [54]
ISteps = interface
procedure DoStep1();
procedure DoStep2();
procedure DoStep3();
end;
IWorker = interface
procedure DoWork();
end
TWorker = interface(IWokrer)
FSteps : IWorker; // Либо инжектируется в конструктор, либо создается там же.
end;
procedure TWorker.DoWork(base: IBase);
begin
FSteps.DoStep1();
FSteps.DoStep2();
FSteps.DoStep3();
end;
Шаблонность сохраняется.
← →
Alkid © (2010-03-09 11:10) [58]Тьфу, поправочка:
TWorker = interface(IWokrer)
FSteps : ISteps; // Либо инжектируется в конструктор, либо создается там же.
end;
← →
jack128_ (2010-03-09 11:15) [59]
> Шаблонность сохраняется.
ну как же она сохраняется то, если мы мы работаем через интерфейс IWorker?
← →
oxffff © (2010-03-09 11:16) [60]
> Alkid © (09.03.10 11:06) [56]
>
> > oxffff © (09.03.10 10:55) [55]
>
> А я писал, что подтип и подкласс - не синонимы, что допустимо
> порождать подкласс, не являющийся подтипом, и что за касты
> расстреливать надо на месте :)
>
> Смотри [44], откуда все началось.
Что смотреть?
Я еще раньше написал [28], что изменение видимости в сторону уменьшения пагубно влияет на отношении подтипов при сохранении отношения формально подклассов.
Началось все с [28]. Где речь шла о наделении языка такой возможностью, при сохранении остальной части.
← →
Alkid © (2010-03-09 11:21) [61]
> jack128_ (09.03.10 11:15) [59]
Тогда поясни, что ты имеешь в виду под шаблонностью. Я думал, что ты под шаблоном понимаешь метод DoWork, который оперирует методами DoStepX(), реализация которых может быть подменена в наследниках. Так?
Здесь имеем тоже самое, только реализация подменяется не путем наследования, а путем инжектирования другой реализации ISteps. Это, кстати, вполне себе обычный паттерн, который применяется и без залезания в те дебри, в которые я вознамерился тут залезть :)
← →
Alkid © (2010-03-09 11:24) [62]
> oxffff © (09.03.10 11:16) [60]
Понятно, имеется некий мисандерстендинг :) Там ты отвечал на пост Игоря :)
Короче, я хочу странного, но не настолько, что бы сохранять отношение подтипа с закрытым наследованием :) Считаю, что этот вопрос исчерпан :)
← →
jack128_ (2010-03-09 11:27) [63]
> Я думал, что ты под шаблоном понимаешь метод DoWork, который
> оперирует методами DoStepX(), реализация которых может быть
> подменена в наследниках. Так?
именно + то, что этот метод НЕвиртуален. ТО есть мы фиксируем реализацию этого метода, не даем никому её подменить. В твоем же коде - я всегда могу написать свой реализатор IWorker который будет делать все что хочешь, только не вызывать шаги.
собственно я ж написал как эту проблему избежать, нужно просто вызов шагов загнать в обычную процедуру (см [54])
← →
Alkid © (2010-03-09 11:30) [64]
> jack128_ (09.03.10 11:27) [63]
А, ты об этом. Ну да, можно и так сделать. Это не влияет на замену наследования делегирования.
← →
jack128_ (2010-03-09 11:32) [65]у мя в [54] еще второй пункт есть. по поводу того, что в исходном коде DoStepX() - доступны только подклассам - а в твоем варианте - они доступны кому угодно
← →
Игорь Шевченко © (2010-03-09 12:25) [66]Не удержусь:
"ОО-языки упрощают абстракцию, возможно, даже слишком ее упрощают. Они поддерживают
создание структур с большим количеством связующего кода и сложными уровнями.
Это может оказаться полезным в случае, если предметная область является
действительно сложной и требует множества абстракций, и вместе с тем такой
подход может обернуться неприятностями, если программисты реализуют простые
вещи сложными способами, просто потому что им известны эти способы и они умеют
ими пользоваться.
Все ОО-языки несколько сколнны "втягивать" программистов в ловушку избыточной
иерархии. Чрезмерное количество уровней разрушает прозрачность: крайне
затрудняется их просмотр и анализ ментальной модели, которую по существу
реализует код. Всецело нарушаются правила простоты, ясности и прозрачности,
а в результате код наполняется скрытыми ошибкми и создает постоянные проблемы
при сопровождении.
Данная тенденция, вероятно, усугубляется тем, что множество курсов по
программированию преподают громоздкую иерархию как способ удовлетворения
правила представления. С этой точки зрения множество классов приравнивается
к внедрению знаний в данные. Проблема данного подхода заключается в том, что
слишком часто "развитые данные" в связующих уровнях фактически не относятся
у какому-либо естественному объекту в области действия программы -
они предназначены только для связующего уровня.
Одной из причин того, что ОО-языки преуспели в большинстве характерных для них
предметных областей (GUI-интерфейсы, моделирование, графические средства),
возможно, является то, что в этих областях относительно трудно неправильно
определить онтологию типов. Например, в GUI-интерфейсах и графических средствах
присутствует довольно естественное соотвествие между манипулируемыми
визуальными объектами и классами. Если выясняется, что создается большое
количество классов, которые не имеют очевидного соответствия с тем, что
происходит на экране, то, соотвественно, легко заметить, что связующий уровень
стал слишком большим.
"
Эрик Реймонд, "Искусство программирования для Unix"
← →
Alkid © (2010-03-09 12:37) [67]
> Игорь Шевченко © (09.03.10 12:25) [66]
и-и-и? ;) Какая связь с обсуждаемым вопросом?
← →
Игорь Шевченко © (2010-03-09 13:11) [68]Alkid © (09.03.10 12:37) [67]
Скорее, с развитием и ответвлениями обсуждаемого вопроса.
← →
Alkid © (2010-03-09 13:35) [69]
> Игорь Шевченко © (09.03.10 13:11) [68]
А, понятно. Просто то, что я предлагаю, на количество уровней абстракции не влияет. Те же яйца, вид сбоку, если в двух словах :)
← →
oxffff © (2010-03-09 14:34) [70]
> Alkid © (09.03.10 11:24) [62]
>
> > oxffff © (09.03.10 11:16) [60]
>
> Понятно, имеется некий мисандерстендинг :) Там ты отвечал
> на пост Игоря :)
> Короче, я хочу странного, но не настолько, что бы сохранять
> отношение подтипа с закрытым наследованием :) Считаю, что
> этот вопрос исчерпан :)
Отношение подтипа с закрытым наследованием можно сохранить, если выдать свой собственный интерфейс идентичный необходимому типу(например супертипу)(однако возникнет проблема бинарной совместимости, поскольку смещения поменяются. Но если изменить способ обращения(исполнения кода, например интерпретатор) без привязки к смещению, то это можно решить. Более того есть такие реализации без "вертикальной сабтипизациии".
← →
Piter © (2010-03-09 14:54) [71]Игорь Шевченко © (09.03.10 12:25) [66]
Эрик Реймонд, "Искусство программирования для Unix"
Игорь, я так понимаю вы в настоящее время интересуетесь программингом в сторону *nix платформ.
Если не сложно - посоветуйте что прочитали, что думаете, какие книжки особо понравились, какой нужен уровень для их корректного прочтения?
Еще вопрос - какие языки, среды, технологии используете для программинга под *nix? Вас интересует именно *nix как таковой или в сфере кросс-платформенных приложений? На чем остановились?
P.S. Эрик C. Реймонд - Искусство программирования для Unix, это я так понимаю как раз ликбез-обзор по существующим технологиям?
← →
Alkid © (2010-03-09 15:02) [72]
> oxffff © (09.03.10 14:34) [70]
Интерфейсы спасут отца русской демократии от бинарной совместимости. С другой стороны, зачем сохранять отношения подтипа, если закрытое наследование для того и сделано, что бы это отношение ликвидировать? :)
← →
oxffff © (2010-03-09 15:22) [73]
> Alkid © (09.03.10 15:02) [72]
>
> > oxffff © (09.03.10 14:34) [70]
>
> Интерфейсы спасут отца русской демократии от бинарной совместимости.
> С другой стороны, зачем сохранять отношения подтипа, если
> закрытое наследование для того и сделано, что бы это отношение
> ликвидировать? :)
От бинарной несовместимости? :)
Вот вот и я думаю, что в твоем вопросе [0] интерфейсы спасут тебя. :)
А Delphi impelements наделит тебя необходимой силой воина со сложностью. :)
Закрытое наследование является формой агрегации реализации. Отношение подтипа можно сохранить например для того, чтобы внести в реализацию некие изменения, полностью заменив или частично. Однако получается, что привычная VMT уже не нужна. А приобретает некую форму разрешения как для мультиметода в run time.
← →
GDI+ (2010-03-09 19:33) [74]
> Некто (08.03.10 13:27)
>
> При спорах вида "С++ vs X", где Х - любой объектно-ориентированный
> ЯП, поддерживающий единичное наследование, неизбежно возникает
> ответвление спора на тему "множественное наследование vs.
> единичное наследование". Защитники МН упирают на бОльшую
> гибкость и возможности, которые дает МН, противники - на
> то, что МН усложняет реализацию языка, сам язык и что МН
> вообще не нужно.
Множественное наследование необходимо. Без него никак. Но в нормальных языках множественное наследование реализовано через интерфейсы.
А множественное наследование реализации, а не декларации это изврат и нигде не используется.
← →
GDI+ (2010-03-09 19:34) [75]
> Игорь Шевченко © (08.03.10 13:51) [7]
>
> Есть множественное наследование интерфейса и множественное
> наследование реализации. Хорошо и то, и другое.
Плохо. Хотя, если цель обфускация кода, то хорошо.
← →
Игорь Шевченко © (2010-03-09 19:42) [76]GDI+ (09.03.10 19:33) [74]
> А множественное наследование реализации, а не декларации
> это изврат и нигде не используется.
Кругозор надо расширять, не будешь ерундой болтать
← →
Alkid © (2010-03-09 19:50) [77]
> GDI+ (09.03.10 19:33) [74]
> Множественное наследование необходимо. Без него никак. Но
> в нормальных языках множественное наследование реализовано
> через интерфейсы.
>
> А множественное наследование реализации, а не декларации
> это изврат и нигде не используется.
Аргументируй.
Кстати, насчет "нигде не используется" ты не прав. В stl очень даже используется в виде trait-классов. На прошлой работе применял множественное наследования для реализации mixin-style.
Так что хочу услышать аргументированное изложение недостатков множественного наследования.
← →
GrayFace © (2010-03-11 02:41) [78]oxffff © (08.03.10 21:34) [28]
Этой возможности быть и не должно. :)
Поскольку, если B является подклассом A, то B является подтипом A.
Если позволить менять видимость, то тогда B не будет являться подтипом A.
Поскольку B не может выступить в качестве А
(нарушение типобезопасности, то есть язык будет являться небезопасным)
Лучше было бы, если бы была. Это очень полезно для published свойств, иногда полезно для public. При приведении к A эти методы можно будет вызвать. Т.е. прятанье должно быть чисто внешнее.
А то, как сейчас, плодить TCustom*, вписывать в published свойства под все версии Delphi - это не дело.
Спасибо за implements!
← →
oxffff © (2010-03-11 08:40) [79]
> Лучше было бы, если бы была. Это очень полезно для published
> свойств, иногда полезно для public. При приведении к A эти
> методы можно будет вызвать. Т.е. прятанье должно быть чисто
> внешнее.
> А то, как сейчас, плодить TCustom*, вписывать в published
> свойства под все версии Delphi - это не дело.
Это всего лишь реализация VCL. К формальной теории отношения не имеет.
← →
GrayFace © (2010-03-12 15:10) [80]oxffff © (11.03.10 8:40) [79]
Это всего лишь реализация VCL. К формальной теории отношения не имеет.
При чем тут реализация VCL? Это свойство языка, которое было бы полезным.
Речь была о
Классические пуристы возражают против наследников, например, от TList. Их аргументы таковы, что наследнику в большинстве случаев не нужны методы предка Exchange, Move, и т.д.
Нету в Delphi возможность понизить область видимости - ну такой язык.
С этим данное "частичное" понижение видимости отлично бы справилось.
← →
oxffff © (2010-03-12 17:18) [81]
> GrayFace © (12.03.10 15:10) [80]
> oxffff © (11.03.10 8:40) [79]
> Это всего лишь реализация VCL. К формальной теории отношения
> не имеет.
>
> При чем тут реализация VCL? Это свойство языка, которое
> было бы полезным.
Мой ответ связан с твоим тротестом против опубликования свойств в Custom. Причем здесь свойство языка и опубликование свойств?
> Речь была о
> Классические пуристы возражают против наследников, например,
> от TList. Их аргументы таковы, что наследнику в большинстве
> случаев не нужны методы предка Exchange, Move, и т.д.
>
> Нету в Delphi возможность понизить область видимости - ну
> такой язык.
>
> С этим данное "частичное" понижение видимости отлично бы
> справилось.
А почему бы с этим не справится в рамках стандартной модели?
Объект делегатор с агрегатом внутри чем не устраивает?
← →
GrayFace © (2010-03-12 21:09) [82]Я не против опубликования свойств в Custom. Я говорил о том, что это сейчас единственный нормальный вариант не тащить в свой компонент лишние и вредные свойства. Но это очень неудобный вариант, приводящий к тому, что приходится следить за версиями VCL и добавлять новые свойства, появившиеся в VCL, в компонент.
oxffff © (12.03.10 17:18) [81]
А почему бы с этим не справится в рамках стандартной модели?
Объект делегатор с агрегатом внутри чем не устраивает?
<Посмотрев TList> Всем устраивает.
← →
oxffff © (2010-03-12 23:08) [83]
> GrayFace © (12.03.10 21:09) [82]
> Я не против опубликования свойств в Custom. Я говорил о
> том, что это сейчас единственный нормальный вариант не тащить
> в свой компонент лишние и вредные свойства. Но это очень
> неудобный вариант, приводящий к тому, что приходится следить
> за версиями VCL и добавлять новые свойства, появившиеся
> в VCL, в компонент.
Какое отношение VCL имеет к языку Delphi?
> <Посмотрев TList> Всем устраивает.
Не понял.
← →
GrayFace © (2010-03-13 20:32) [84]oxffff © (12.03.10 23:08) [83]
Какое отношение VCL имеет к языку Delphi?
Прямое. Достаточно того, что он написан на Delphi. В VCL активно используются published и наследование. При совмещении этих 2 вещей проблема прятанья published свойств неизбежно встает. Тебе не нравится, что проблема иллюстрируется на конкретной библиотеке?
oxffff © (12.03.10 23:08) [83]
Не понял.
Объект делегатор с агрегатом внутри Всем устраивает.
← →
oxffff © (2010-03-13 23:19) [85]
> GrayFace © (13.03.10 20:32) [84]
> oxffff © (12.03.10 23:08) [83]
> Какое отношение VCL имеет к языку Delphi?
> Прямое. Достаточно того, что он написан на Delphi. В VCL
> активно используются published и наследование. При совмещении
> этих 2 вещей проблема прятанья published свойств неизбежно
> встает. Тебе не нравится, что проблема иллюстрируется на
> конкретной библиотеке?
Считаю язык - это язык. А VCL - это один из возможных результатов применения инструмента(языка).
Поясни где проблема по твоему мнению при совмещении наследования и published в VCL.
← →
oxffff © (2010-03-13 23:26) [86]
> GrayFace © (13.03.10 20:32) [84]
Для сериализации в VCL есть еще TPersistent.DefineProperties и использование RTTI в виде published. Достаточно продуманно.
← →
GrayFace © (2010-03-19 14:23) [87]oxffff © (13.03.10 23:19) [85]
Поясни где проблема по твоему мнению при совмещении наследования и published в VCL.
У меня был ListView, в котором мне надо было спрятать свойства LargeImages, SmallImages и еще несколько. Важно, чтобы они не показывались в редакторе свойств. Этот компонент, к тому же, наследовался от другого моего компонента. Чтобы это сделать, надо либо создавать TCustom варианты, а при наследовании от них расшаривать все желательные свойства, но надо знать список этих свойств для каждой версии Дельфи - вся проблема в этом - в каждой версии добавляются новые, а мне надо только спрятать несколько старых свойств. Я ошибся в своем утверждении - проблема в совмещении 3 вещей - наследования, published и использования списка всех published свойств для показа кому-то.
oxffff © (13.03.10 23:26) [86]
Для сериализации в VCL есть еще TPersistent.DefineProperties и использование RTTI в виде published. Достаточно продуманно.
Да, интересно. Надо будет попробовать - может так получится спрятать.
← →
oxffff © (2010-03-19 14:41) [88]
> GrayFace © (19.03.10 14:23) [87]
> oxffff © (13.03.10 23:19) [85]
> Поясни где проблема по твоему мнению при совмещении наследования
> и published в VCL.
> У меня был ListView, в котором мне надо было спрятать свойства
> LargeImages, SmallImages и еще несколько. Важно, чтобы они
> не показывались в редакторе свойств. Этот компонент, к тому
> же, наследовался от другого моего компонента. Чтобы это
> сделать, надо либо создавать TCustom варианты, а при наследовании
> от них расшаривать все желательные свойства, но надо знать
> список этих свойств для каждой версии Дельфи - вся проблема
> в этом - в каждой версии добавляются новые, а мне надо только
> спрятать несколько старых свойств. Я ошибся в своем утверждении
> - проблема в совмещении 3 вещей - наследования, published
> и использования списка всех published свойств для показа
> кому-то.
1. Нужно наследоваться от самого закрытого и раскрывать все что-нужно.
2. Либо наследование от TControl и делегирование нужному контролу.
Полное делегирование с идентичным временем жизни=наследованию, хотя в большинстве случаев не бинарно совместимо.
3. Всегда есть возможность сделать run-time правки или перекрыть методы участвующие в сериализации.
← →
GrayFace © (2010-03-19 23:49) [89]oxffff © (19.03.10 14:41) [88]
1. Нужно наследоваться от самого закрытого и раскрывать все что-нужно.
Я и говорю - это надо от всех Дельфей иметь модули.
← →
GrayFace © (2010-03-20 00:03) [90]Чтобы написать
{$IFDEF D2006}
// список пропертей, в нем появившихся
{$ENDIF}
Страницы: 1 2 3 вся ветка
Форум: "Прочее";
Текущий архив: 2010.08.27;
Скачать: [xml.tar.bz2];
Память: 0.78 MB
Время: 0.063 c