Считается, что некоторые языки поддерживают более «чистую» модель ООП, чем другие. (К ним мы применяем термин «радикально объектно-ориентированный».) Это означает, что любая сущность в языке является объектом, даже примитивные типы представлены полноценными классами, а переменные и константы рассматриваются как экземпляры. В таких языках, как Java, C++ и Eiffel, дело обстоит иначе. В них примитивные типы (особенно константы) не являются настоящими объектами, хотя иногда могут рассматриваться как таковые с помощью «классов-оберток». Вероятно, есть языки, которые более радикально объектно ориентированы, чем Ruby, но их немного.
Большинство объектно-ориентированных языков статично; методы и атрибуты, принадлежащие классу, глобальные переменные и иерархия наследования определяются во время компиляции. Быть может, самый сложный концептуальный переход заключается в том, что в Ruby все это происходит динамически. И определения, и даже порядок наследования можно задавать во время исполнения. Честно говоря, каждое объявление или определение исполняется во время работы программы. Помимо прочих достоинств, это позволяет избавиться от условной компиляции, и во многих случаях получается более эффективный код.
На этом мы завершаем беглую экскурсию в мир ООП. Мы старались последовательно применять введенные здесь термины на протяжении всей книги. Перейдем теперь к краткому обзору самого языка Ruby.
1.2. Базовый синтаксис и семантика Ruby
Выше мы отметили, что Ruby — настоящий динамический объектно-ориентированный язык.
Прежде чем переходить к обзору синтаксиса и семантики, упомянем некоторые другие его особенности.
Ruby — прагматичный (agile) язык. Он пластичен и поощряет частую переработку (рефакторинг), которая выполняется без особого труда.
Ruby — интерпретируемый язык. Разумеется, в будущем ради повышения производительности могут появиться и компиляторы Ruby, но мы считаем, что у интерпретатора много достоинств. Он не только позволяет быстро создавать прототипы, но и сокращает весь цикл разработки.
Ruby ориентирован на выражения. Зачем писать предложение, когда выражения достаточно? Это означает, в частности, что программа становится более компактной, поскольку общие части выносятся в отдельное выражение и повторения удается избежать.
Ruby — язык сверхвысокого уровня (VHLL). Один из принципов, положенных в основу его проектирования, заключается в том, что компьютер должен работать для человека, а не наоборот. Под «плотностью» Ruby понимают тот факт, что сложные, запутанные операции можно записать гораздо проще, чем в языках более низкого уровня.
Начнем мы с рассмотрения общего духа языка и некоторых применяемых в нем терминов. Затем вкратце обсудим природу программ на Ruby, а потом уже перейдем к примерам.
Прежде всего отметим, что программа на Ruby состоит из отдельных строк, — как в С, но не как в «древних» языках наподобие Фортрана. В одной строке может быть сколько угодно лексем, лишь бы они правильно отделялись пропусками.
В одной строке может быть несколько предложений, разделенных точками с запятой; только в этом случае точка с запятой и необходима. Логическая строка может быть разбита на несколько физических при условии, что все, кроме последней, заканчиваются обратной косой чертой или лексическому анализатору дан знак, что предложение еще не закончено. Таким знаком может, например, быть запятая в конце строки.
Главной программы как таковой (функции main
) не существует; исполнение происходит сверху вниз. В более сложных программах в начале текста могут располагаться многочисленные определения, за которыми следует (концептуально) главная программа. Но даже в этом случае программа исполняется сверху вниз, так как в Ruby все определения исполняются.
1.2.1. Ключевые слова и идентификаторы
Ключевые (или зарезервированные) слова в Ruby обычно не применяются ни для каких иных целей. Вот их полный перечень:
BEGIN END alias and begin
break case class def defined?
do else elsif end ensure
false for if in module
next nil not or redo
rescue retry return self super
then true undef unless until
when while yield