Послесловие от переводчикаВ докладе 1995го года упоминаются незнакомые компиляторы и языки программирования, и, наверное, возникает вопрос, а как дела с более привычными технологиями.
Во-первых, для разработчиков на Delphi нужно сделать пояснение, что в Delphi все метаклассы образуют теневое дерево, повторяющее дерево наследования обычных классов. К каждому метаклассу можно обратиться, указав "class of ...". Так,
type System.TClass = class of System.TObject. Каждый раз, когда описывается новый класс, на самом деле, создаётся два, обычный и теневой. Все простые методы добавляются в обычный класс, а все так называемые классовые методы — в метакласс. Однако, в Delphi нет аналога полей метакласса. class var в самых новых версиях Delphi — это синтаксический сахар для глобальных переменных. В Delphi System.TClass не является дочерним классом System.TObject, и переменую типа System.TClass нельзя присвоить переменной System.TObject. И, конечно, нельзя явно указать метакласс. Таким образом, метаклассы есть, но они герметично изолированы от просто классов. Это называется «неявными метаклассами».
Язык Ada в этом отношении ещё менее развит, чем Delphi. Аналогом System.TClass является
Ada.Tags.Tag. Кроме запроса имени, исследования иерархии и установления родства, максимум полезного, что можно сделать, — это
использовать виртуальный конструктор при помощи Ada.Tags.Generic_Dispatching_Constructor, однако если виртуальный конструктор даже и не собирается создавать никакой объект, а бросит исключение, перед этим чего-нибудь поделав с аргументами, то уже получается аналог классовых методов. Только это отличает тэги от просто RTTI. Примерно на таком же уровне поддержка метаклассов в Java и .NET. Там классы представлены некоторыми объектами, но классовые методы не являются методами этого объекта.
В Objective-C, как и в Smalltalk, метаклассы неявные, однако, в отличие от Delphi, метаклассы имеют общий корень с обычными объектами. Нет определённости, однако, каким образом ядро Objective-C создаёт метаклассы. Оно может создавать теневую иерархию метаклассов параллельно обычной иерархии, а может производить метаклассы для каждого класса от одного родителя. Метаклассы в Objective-C — это вообще слабо изученная тема. Интересующихся могу направить почитать статью «
Метаклассы в Objective-C». Они существуют на уровне ядра Objective-C, но не на уровне языка программирования. Выглядит так, как будто разработчики языка испытали потребность добавить классовые методы, и переиспользовали для этого механизм вызова методов, как у обычных объектов, тем самым положив начало метаклассам, но не были готовы развить эту тему и так и зарыли их в ядре Objective-C.
Поскольку разработчик Python вдохновлялся «Putting Metaclasses to Work», то там метаклассы есть, но книгу эту до меня никто не сканировал, не выкладывал в сеть, и как этим пользоваться, было не всем понятно.
Что касается собственно RRBC, то и Delphi, и Ada, и C++ все аналогичны C++ в таблице. Generic C++. Ни Delta/C++, ни Sun OBI, ни SOM, ничего из этого не помогло им стать лучше. Generic C++, как в 1995м году. Вам могли нахваливать GObject в Linux? Туда же.
Только Objective-C демонстрирует положительную динамику. С появлением
non-fragile ivars (также известное, как non-fragile ABI) была заткнута важная брешь, сноска h в таблице.
Я пытался сделать из Delphi .bpl нечто вроде .NET Framework, чтоб поставил, и остальные приложения по нескольку килобайт были. Это называлось RTL Pak. Очень скоро я не смог угнаться за очередными версиями Delphi, в каждой из которых свои библиотеки RTL и VCL, не подходящие другим версиям Delphi. RTL от GNAT я туда тоже положил, и точно так же он на следующий год устарел.
Для сравнения,
вот тут выложены разные версии YellowBox для Windows, а
вот тут можно скачать SokoSave для YellowBox, и версия для старого OPENSTEP (когда оно ещё даже не называлось YellowBox) будет работать и с OPENSTEP, и с WebObjects 4.0.1 (в которых YellowBox 1.0), и с YellowBox 5.1. Только с версией для WebObjects получается неприятная история. В WebObjects средства разработки лепят во все исполняемые файлы подряд зависимость от библиотеки, которая может посылать сообщения через machd.exe, а так как machd.exe и эта библиотека есть только в WebObjects, версия для WebObjects не запускается на YellowBox 5.1.
При том, что для Objective-C есть, что показать, серьёзным недостатком получается ублюдочный синтаксис, тяжёлое наследие Smalltalk. Каждый раз, как пытаются сделать работу с API на Objective-C из других языков программирования, начинается паралимпиада, а как бы эти ублюдочные селекторы добавить в свой язык программирования. Может быть,
нам эту пакость-таки добавить каким-нибудь макаром в синтаксис, а, может быть,
задвинуть весь селектор в отдельную директиву и жить дальше как люди? Естественным путём добровольно никто в свой язык такой способ записи вызовов методов так и не добавил. Кроме того, в Objective-C плоское пространство селекторов, в то время как методы SOM принадлежат классам.
Таким образом, глядя на экосистему Objective-C, которому больше повезло, можно убедиться, что RRBC — это нужно, но в том, чтобы думать о том, как сделать правильно, полезнее смотреть на SOM, которому повезло гораздо меньше.
У меня получилось немного повзаимодействовать с
SOM 3.0 из Delphi 7. Учитывая, что SOM двадцать лет не развивался, имеет смысл сбросить балласт наследия и начать с нуля. Так что это скорее для лучшего понимания, чем для реального использования.
Во-первых, в то время, как в COM была изначально диктатура Unicode (2-хбайтовые строки), а Objective-C тоже как-то пережил этот переход, в виде UTF-8 хотя бы, SOM встречает нас опостылевшим ANSI. Однобайтовые строки берут начало в стандарте CORBA. В CORBA потом появился wstring (2-хбайтовые строки), а некоторые применения CORBA считают, что все однобайтовые строки UTF-8. Я работал и с 2-хбайтовыми строками в COM, и с однобайтовыми в ANSI и UTF-8, и с четырёхбайтовыми в Ada. Один человек в 2005м году написал
апологетику, как он назвал, Освенциму для однобайтовых строк, и мне с учётом моего опыта работы она понравилась. Если сейчас, 20 лет спустя после Java, которая ему так понравилась, начинать заново, я бы устроил ещё более лютый Освенцим и оставил только четырёхбайтовые строки (UTF-32). Для мира Windows моветон, а взять, допустим,
libidn, там, наоборот, нет UTF-16, а есть только UTF-8 и UTF-32.
Во-вторых, очень неудобно, что нет счётчиков ссылок для почти всего, как в COM и Objective-C. IBM SOM 3.0 их так и не приобрёл. У Apple SOM, кстати, они были. В Objective-C они появились не сразу, переход был где-то между NeXTSTEP и OPENSTEP в 1990x, достаточно давно, а теперь-то там вообще ARC. И в Delphi ARC начинает пролезать (на мобильных платформах есть и в версии для Linux обещают) в дополнение к ARC для интерфейсов, которое уже было. Для исключений счетчика ссылок не было, а потом стало можно заворачивать исключения в исключения, и пришлось сделать
System.AcquireExceptionObject, ещё один способ подсчёта ссылок. В SOM в отсутствие подсчёта ссылок усложняется управление памятью. Причем, если не предпринять некоторых действий, то управление памятью для обычных объектов и для прокси к удалённым объектам DSOM — разное. Начинать сейчас что-то делать без счётчика ссылок — значит, обрекать себя на дурацкие проблемы потом, когда-таки понадобится иметь нескольких владельцев объекта. Значит, ARC должен быть сразу. Есть мысль, что такое устройство связано с тем, что была попытка сделать такой DirectToSOM компилятор C++, который бы мог более менее любой обычный код на C++ компилировать в SOM. Если в C++ нет счетчика ссылок для объектов, то и в SOM он не добавлялся, зато была куча методов типа
somDefaultConstVCopyInit для константных/неконстатных, волатильных/неволатильных конструкторов, деструкторов, операции присвоения. Посмотрев на всё это дело, а также посмотрев на то, как шли дела в C++ with Managed Extensions, C++/CLI, Objective-C++, C++/CX, я понимаю, что всё заканчивается тем, что в языке начинают существовать параллельные иерархии классов, одна из старого C++, другая из соответствующей модели, и все эти заигрывания с «обычным C++» так ничем хорошим нигде не закончились. Зато сейчас есть не только legacy C++ код, но и legacy Objective-C, более многообещающий с точки зрения возможности конвертации.
В-третьих, так как кода для SOM, о котором можно побеспокоиться, почти нет, а кода для Objective-C относительно много, неплохо бы новую модель сделать так, чтобы можно было написать компилятор псевдо-Objective-C, который бы мог перекомпилировать существующий код (вроде GNUStep) под новое ядро. Чтобы это было проще, семантику нового ядра тоже может иметь смысл в некоторых местах подкорректировать подальше от SOM, поближе к Objective-C, но не в ущерб тем возможностям, которые были в SOM. Например, сделать, чтобы вызовы методов у NULL не приводили к ошибке.
В-четвёртых, для разработчиков SOM был важен стандарт CORBA. Можно было скачать SOMobjects Developer Toolkit 3.0, сделать на нём сервер DSOM, потом взять SOM 3.0 Java Client, сделать с его помощью Java-апплет, который по сырым сокетам подключится к серверу и поработает с его объектами. Сейчас это не актуально. Flash вытеснил Java, а теперь уже HTML5 вытесняет Flash. Сырых сокетов в HTML5 нет. Лучше протокол взаимодействия основывать на чём-то, что может работать с WebSockets.
В рамках исследований у меня появляются научные работы. Из того, что опубликовано —
Общая платформа исполнения приложений и
Метод кооперативной эмуляции архитектуры процессора. Делаются заметки в
группе ВКонтакте.