> -- Владислав Жаринов писал(а):
> ...Ну и ещё: Усов также говорил и о поддержке видоизменяемости кода вплоть до момента востребования при исполнении: . Вы не об этом?
Можно и об этом. Оставим в сторонке "ручные" решения, т.е. через "низкоуровневое" манипулирование указателями на функции, лямбдами, делегатами и т.п. Возможность "динамического ООП" встречается в динамических языках, таких как Phyton, Ruby и др. Но не очень-то "системно" (фактически, прямая правка метаданных классов и их экземпляров-объектов). В области, например, Lua можно найти более организованные решения для гибкого ООП, где нет типичной базовой ограничивающей классовости. Есть альтернативы и в области "статических, нативных" языков. Например,Felix- скриптовый ML-подобный язык, со строгой статической типизацией, который на выходе даёт эффективный С++-код. У него удачнаяобъектная система- гибкое и мощное прототипное ООП, которое даёт возможность наследоваться не только от типа (класса), но и от конкретного экземпляра-объекта, с возможностью (необязательной) переопределения или расширения структуры объекта и состава операций, в т.ч. возможно и "подмешивание" объектов (не только наследование, полиморфизм). Через стандартные средства вполне ясно организуется динамическая "замена VMT", т.е. переход на новый согласованный набор операций. Есть также понимание "интерфейсов", которое не требует обязательной модификации кода объектов для их реализации, т.е. есть возможность для обобщения и построения абстракций уже после создания кода, описывающего объекты. При этом рядом существуют "классы", но это классы операций, как классы типов в хаскеле (здесь,здесь) - перегрузка функций по типам (не объектам), всё строго статично, нет никаких динамических виртуальных вызовов.
В общем, имхо, именно такой должна быть модель ООП в мэйнстриме, а не то, что сейчас...

Среди промышленных решений можно ещё отметить "мультиметоды", популярные в "лисп"-ах (например,здесь). Но принципиальный недостаток такой гибкой диспетчеризации вызова методов - производительность (в отличие от модели выше, где весь "оверхед" в типовом виртуальном вызове, которого может и не быть, компилятор по случаю сможет и девиртуализировать).

И в то же время нельзя сбрасывать со счетов и явные инварианты типов. На сегодня технологии продвинулись вперёд, те же "зависимые типы". Правда сейчас это не столь программирование "общего назначения", а, фактически, специализированная область - доказательство теорем (и даже простенькую программу нужно доказывать и доказывать). Но есть положительные попытки значительно упростить зависимые типы - Liquid Types (например,здесьсобраны материальчики, имхоздесьнеплохое начало). Основное - проверка инвариантов на основе логических предикатов для типов, которые могут быть заданы явно и/или получены на основе анализа кода (естественно, при наличии развитой системы типизации). При этом верификатор может выявить отсутствие нужных runtime-проверок, а также в ряде случаев выявить конкретные места, где они должны быть. К примеру, некая функция согласно типам своих аргументов имеет ряд условий для выполнения (в соответствие с предикатами для типов), она их выставляет как требования к удовлетворению для своей вызывающей ф-ции. В свою очередь, та ф-ция вместе со своими требованиями передает их своей выше стоящей (вызывающей) ф-ции, и так далее пока не обнаружится место первичного возникновения данных. Именно здесь нужны соответствующие проверки, после которых целый стэк ф-ций может работать безопасно, без лишних runtime-проверок. В основном, через liquid-types могут быть заданы предикаты для несложной рутинной верификации, типа проверок невыхода из диапазонов, допустимость операций (нельзя работать с файлом, пока он не открыт) и т.п. Такие условия уже могут содержатся внутри кода, а также несложно и негромоздко их определить явно при необходимости (в т.ч. и в сторонке, например, в комментариях, если язык программирования не позволяет).
В общем, продвижения в области вменяемой верификации имеются.

Поэтому, ещё раз акцентирую внимание на том, что у представленных здесь схематичных таблиц есть неплохое свойство -- возможность отражения агрегатной модели вычислений. Ещё раз выкладываю рисунок, где некая ф-ция имеет варианты реализации в зависимости от типа входного аргумента (при этом в исходном коде эта ф-ция может быть определена дважды: у объекта типа Magic и объекта типа Melee, имеющих общего типа-предка Attack), плюс в этой таблице выделен явный столбец для "assert" (и "true" для безусловных исходов), что актуально при использовании верификации или ручных "assert"-ов (этого столбца нет в доке-презентации):
Вложение:
tbl_assert.PNG [ 73.19 КБ | Просмотров: 18546 ]
