Введение
Продолжая писать про io, совершенно необходимо остановиться отдельно на устройстве объектной системы этого чудесатого езычка. Главная проблема в том, что даже если вы «знаете» ООП, вполне может сложиться ситуация, что вы просто не поймете, как оно устроено в io. Сейчас под ООП почему-то подразумевается модель Java, чаще всего. C++ нельзя назвать объектно-ориентированным языком, потому что он язык поддерживающий парадигму ООП, но это не его основная парадигма. Java больше подходит под гордое звание Ъ-ООП языка, но вот беда, ООП диктуемое Java-like языками довольно извращено. Изначально принципы ООП зарождались в Smalltalk'е и там все выглядело несколько иначе, объекты общались друг с другом не посредством вызова методов, а посредством передачи друг другу сообщений, мне до сих пор странно, почему же от это модели ушли, ведь такое построение позволяет ввести прозрачную параллельность в язык без костылей. Посмотрите на нынешние круто параллелящиеся языки, тот же Erlang например, там все сделано через сообщения. Опять же нагородили огородов из RPC, COM и прочего dbus'а. А ведь как все хорошо начиналось.
Прототипное ООП
Мы как-то привыкли к тому, что ООП строится на классах. Класс — описание типа, объект — экземпляр класса. В целом такая модель очень хорошо себя зарекомендовала в нелегком деле разделения логики и данных, однако внесла дополнительную путаницу в программы. Вам нужно держать в голове все экземпляры класса, а так же сам класс. Вопрос, конечно, спорный и желания наезжать на классическую модель «класс-объект» у меня нет, но рассказать о преимуществах прототипов все-таки хочется.
Глянем на прототипы, в двух словах я описывал структуру в первой статье, но на всяких случай напомню. Прототипность языка заключается в том, что напрочь отсутствуют такие понятия как класс, экземпляр класса и прочее связанное с разделением декларации типа и данных, в io есть только объекты. Объект всегда имеет свой инстанс (как это по русски будет?), получить новый объект можно склонировав старый и изменив его свойства, добавив/убрав из него нужные слоты. Таким образом мы убиваем сразу целый косяк грызунов: у нас есть активный объект, свойства/методы которого доступны для использования и он же является прототипом («декларацией класса») для своих потомков. Очень отдаленно (ну о-о-о-очень отдаленно) такая структура напоминает статические классы.
Объекты которые есть всегда
Сразу после запуска интерпретатора вам доступны несколько «глобальных» объектов, пожалуй самые важные из них вот эти:
- Lobby
- Object
factorial := method(number,
if(number == 0,
1,
number * factorial(number - 1)
)
)
factorial(5) print
Создает вовсе не функцию факториал, он создает слот факториал в объекте Lobby.
Lobby является контекстным объектом, пока явно контекст не переключается на другой объект.
Немножко вуду
Объекты в io интроспективны, то есть вы можете копаться у них в кишках как вашей извращенной натуре только захочется, если у вас есть какой-то непонятный объект, вы всегда можете посмотреть чего у него внутре (печеньки неонка!).
Lobby slotNames printЭто уже началось метапрограммирование, тема отдельной статьи, пока я только упомяну то, что вы можете «на лету» делать с объектами такие штуки, которые ни в одном немецком фильме не показывают.
Модульность
Может это и тема отдельной статьи, но пробежаться надо в любом случае. Конечно io модульный язык, иначе не могло быть просто потому, что не могло быть. Причем модульность в io сделана крайне прикольным образом, тут нет никаких import/include/require_once, тут все проще. Есть некий модуль Z_Importer, который загружается вместе с интерпретатором в память, как только вы пытаетесь использовать какой-либо объект не входящий в лексический обзор текущего файла, этот самый модуль ломится искать файл с именем класса. Сначала в текущем каталоге, потом по каталогам библиотек (указываемым методом addSearchPath). Допустим классы Mushroom, Lenin и Man из первой статьи лежат в отдельных файлах. Как описать мужика?
Mushroom //Достали грибочек из Mushroom.io Lenin //Достали Владимирильича из Lenin.io Man //Достали мужыка из Man.io Man eat(Mushroom) Man state printlnПо-моему это самый дзэнский импортер из всех, которые я видел (:
Ну и все, пожалуй
Вроде бы это все, что нужно знать о объектной модели io, главное помнить про сообщения, но это уже совсем другая история (:
13 коммент.:
инстанс - экземпляр
ты чем так нескушно пишешь, неушто мозгом?
Емаксом (:
"проглотил" 3 статьи про IO на одном дыхании!
Жду ещё!
Это прекрасно
Спасибо, чувак! Отличный язык, за душу взяло.
instance (экземпляр) бывает не у объекта а у класса, в Io классов нет соответственно нет и экземпляров.
PS. А с учетом что классы сами могут быть объектами, то в этой ООП терминологии можно вообще мозги вывихнуть.
может тогда не экземпляр, а ссылка??
instance -- конкретный объект. Получается он образец самого себя. И прототип своих клонов. чУднО то как!
экземпляр, экземпляр -- есть сложившаяся терминология.
Экземпляр класса (объект), экземпляр объекта (инстанс).
Ну да, классы сами по себе могут быть объектами (типа класс, метаклассы в смоллтоке, MOP в CLOS). Чего тут такого выносмозгвыносящего? Методы этого метакласса КлассОбъектов -- это рефлексия и интроспекция по перебору методов/свойств, добавлению метода (нового) в динамической типизации, и т. п.
Вполне смоллтоково, а вот прототипы в Self или JavaScript просто уносят лишнее понятие типа класса , оставляя только сам класс=объект :))
Правда, прототипное ОО чего-то не очень быстро работает. Тесты на shootout по Self/JavaScript/io/Lua/Smalltalk эту тенденцию в целом показывают.
""Еще! Еще!" - кричали веселые дети" (с) из бонифация
Существующие так многословны, содержат исключения из общей логики. IO, похоже, исключение.
Уважаю тебя(Вас) за желание понять новое и за доступное описание
Спасибо большое, приятно. Io далеко не исключение, есть множество хороших языков построенных по принципу «kiss». Весь секрет успеха таких штук заключен в минимальном (но не примитивном) наборе легко понимаемых абстракций. Для Lisp это списки (пары) и функции/анонимные функции, для haskell это система типов и лямбда-исчисление, для io это абсолютная объектность, для Erlang это процесс и так далее.
Отправить комментарий