Что-то по поводу SPLang гуглится нечто иное. Видимо, вместо SPLang подразумевается SLang (действительно любопытный, однако), который гуглится на смежной ветке форума:
https://forum.oberoncore.ru/viewtopic.php?f=12&t=6227В дополнение к материалам по ссылке выше нашлось уточнение используемых принципов множественного наследования (расширения типов):
Концепция наследования в современных языках программированияИ вот хотя бы на примере того же ООП на сегодня наблюдается проблематичность создания некоего единого "лексикона" программирования для всего IT -- широкий разнобой в принципах реализации, а также и в базовых теоретических построениях.
Чуть детальнее изложения для примера, на основе принципов в SPLang и некоторых последних тенденциях в IT (сопоставить существующие положения в прочем мейнстриме -- элементарно). Проблематика множественного наследования кроме статейки выше неплохо раскрыта здесь (с вариантом реализации):
CZ: Multiple Inheritance Without DiamondsАвторы SLang пошли своим путём -- при наследовании (расширении) не используется дублирование функционала (вместо "подобъектов" в основе аля виртуальное наследование по мотивам С++), плюс по-обероновски привязка функций к типу (с соответствующим понятием совместимости типов или "conformance" в терминологии авторов). А также основная фишка -- расширенная перегрузка операций на основе типов с учётом иерархии -- как развитие обероновской концепции универсальной шины сообщений, уменьшающее потребность в операторах вида case/with (или "if ... is ..." в SLang) для ручного тестирования типов и дающая возможность разнести предметную обработку данных по разным функциям. Подробнее, напр., см. слайд 19 "Множественное переопределение" в презентации:
Проект СЛанг: текущее состояние и перспективыК сожалению, неизвестны (или я не заметил) технические детали реализации "двойной диспетчеризации" (а то и более, аля "мультиметоды" по мотивам Лиспов), что может быть ключевым аспектом для производительности и т.д. Или же, к примеру, если взглянуть на "безопасное и надежное программное обеспечение" на Ada:
https://forum.oberoncore.ru/viewtopic.php?f=12&t=6220, то можно обратить внимание на существование запрета в ряде стандартов безопасности динамической диспетчеризации. В Ada есть специальная "прагма" для отключения возможности использования ООП ("теговых" record-ов и интерфейсов). Причины разные: требования к производительности (чтобы не было виртуальности на каждый чих), необходимость доказательства отсутствия недостижимых участков кода, и др. В Safety-Critical Java также есть некоторые запреты виртуальных вызовов, но в целом (где ООП сплошь виртуальное) профиль требует от платформы определение всех вариантов виртуального вызова, т.е. иерархия возможных классов должна быть статически детерминирована (что даёт возможность и для оценок временных затрат при потребности).
В общем случае для различных задач адаптацию к "ручной шине сообщений" не стоит игнорировать. В этом плане современные тенденции вокруг "теории типов" имеют свой подход. Пример реализации "открытых" enum-ов (вариантов) на диалекте ML (в данном случае язык фактически есть препроцессор для С++):
Open RecursionПонятие "перечисления" (enum) есть основополагающее и в SLang. В ML-кругах в рамках "объектности" перечисляют исполняемые (назначаемые) роли, соответственно при расширении перечислимых типов дублирования ролей не возникает (как и "дублирования чисел"), как и в SLang. Однако, ключевое в модели открытых перечислений -- возможность
ковариантности в аргументах функций (см. Subtyping and Variance), что уже на базе типизации детерминирует верхнюю границу расширения типа (в результате, к примеру, для какой-то процедурной переменной (или функционального типа), объявленной с "узким" базовым типом, можно назначать функции с расширенным типом).
В остальном в рамках ООП также наблюдаются расхождения. К примеру, в SLang определено понятие "мультитипов" -- типов с общими свойствами, см., напр., презентацию "Beyond C++: SLang" слайд 50:
http://plc.sfedu.ru/files/slides/days-2-3/Kanatov.pptxПрочие детали неизвестны. В большинстве аля мейнстримных языков для этого используются "интерфейсы", как правило с динамической диспетчеризацией (и ряд предопределенных стандартных операций для статической перегрузки, как арифметические операторы). В ML/Haskell же классы типов со статической диспетчеризацией. И последние тенденции в "теории типов" -- использовать расширение записей (record-ов или структур) для гибкой динамической диспетчеризации с "ручным управлением" доступности наследуемых (расширяемых/переопределяемых) свойств:
теория --
Extensible records with scoped labelsпример практики (тот же диалект ML) --
Row PolymorphismЧастично техника расширения записей выше идентична таковой в SLang, где для управления именами свойств используется оператор "use" (в основном при конфликтах, или только ? -- пока непонятно). В SLang кроме расширения типов ничего не указано насчёт их "сужения" (кроме перечислимых типов как числовые диапазоны или наборы констант, но не структур/методов). Для Оберонов попытка сужения типов была в Lagoona (собственно то, там прежде всего расширение типов особенное):
https://forum.oberoncore.ru/viewtopic.php?f=30&t=6131&start=80#p102851В тех же ML сужение (opaque-типы) основывается на принципах задаваемой структурной эквивалентности, на примере ещё одного упрощённого диалекта (в самом StandartML и производных необходимо "программировать" сигнатуры/структуры/функторы):
http://dot.planet.ee/yeti/intro.html#opaque-typesКроме ООП наблюдается расхождение даже в самых базовых понятиях. В презентации "Beyond C++: SLang" (по ссылке выше) слайд 35 о типах-кортежах вызывает, как минимум, настороженность:
Код:
/*So, Tuple may be typed – (Integer, Real, Boolean)*/
t2 is (Integer, Real, Boolean) /* That is in fact call to Tuple constructor and it will work only when Integer, Real and Boolean have init with no arguments!!! */
t2(1) := 5; t2 (2) := 5.5; t2 (3) := True
/*So, tuple may have named fields*/
t3 is (i: Integer; r: Real; b: Boolean)
t3.i := 5; t3.r := 5.5; t3.b := False
t4: (Integer, Real, Boolean) is (5, 5.5, True)
t5 is (5, 5.5, True)
//Note!
goo (x: Integer) is StandardIO.print (“goo 1\n”) end
goo (x: (Integer)) is StandardIO.print (“goo 2\n”) end
/* These are 2 different routines!*/
goo (5) // output -> goo 1
t6: (Integer) is (5)
goo (t6) // output -> goo 2
goo ((5)) // output -> goo 1 as we treat (<expr>) as expression!!!
goo (5,6,7,8) // output -> goo 2
То, что в "goo (x: Integer)" и "goo (x: (Integer))" разные типы аргументов (во втором случае -- якобы кортеж из одного элемента, как и объявление "кортежной" переменной t6) и соответственно возникают разные перегрузки операций -- пока вводит непонятность, как реализовывать "variadic template" в каком-то виде при наличии то дженериков в языке. А вызов "goo ((5))" не задаёт вариант кортежа (по естественным причинам), но фактически противоречит установленным принципам типизации -- в общем, академическая работа какая-то.
Короче говоря, на сегодня какой-то глобальный "лексикон" возможен лишь как аля алгоритмическая алгебра у Глушковцев -- некие общие математические построения возможны, но при попытках детализации возникают алгебраические "клоны" (разделы) -- для "структурного программирования" и т.д.