Если вы впервые посмотрите на Ruby код, он скорее всего напомнит вам некоторые используемые вами языки. Это не случайно. Большинство синтаксических конструкций покажутся знакомыми пользователям Perl, Python и Java, так что, если вы уже писали на них, изучить Ruby окажется проще простого.
Эта страница состоит из двух частей. В первой содержится попытка сверхкратко описать, что вас ждет при переходе с языка Х на Ruby. Вторая рассказывает об основных особенностях языка, и как эти особенности соотносятся с тем, что вы уже знаете.
Чего ожидать после языка Х на Ruby
Важные замечания по поводу языка и подсказки
Тут собрано несколько подсказок и советов по основным особенностям Ruby, которые вы увидите по мере изучения языка
Итерации и циклы
Две особенности Ruby, отличающиеся от всего ранее увиденного, но к которым
надо привыкнуть - это “блоки” и итераторы. Вместо того, чтобы итерироваться
по индексу (как в С, С++ и pre-1.5 Java), или по списку (как в Perl
for (@a) {...}
, или в Python for i in aList: ...
),
в Ruby зачастую вы увидите
За более подробной информацией о each
(и сопутствующих collect
, find
,
inject
, sort
, и т.д.), обращайтесь к ri Enumerable
(и ri Enumerable#имя_функции
).
Все имеет значение
В Ruby нет разницы между выражением и оператором. Все имеет значение, даже если это значение - nil. Вот так:
Символы - это не “легковесные” строки
Многие начинающие натыкаются на проблему понимания, что такое “символ” в Ruby, и для чего он предназначен.
Символы лучше всего сравнить с уникальными идентификаторами. Символ это скорее сам
знак, а не то, что он означает. Запустите irb
, чтобы почувствовать разницу:
Метод object_id
возвращает уникальный идентификатор объекта. Если два объекта
имеют одинаковый object_id
, то это один и тот же объект (указатель на один
объект в памяти).
Как вы видите, как только вы используете символ, любой другой символ, идентичный
по написанию с первым, будет обращаться к тому же объекту в памяти. У всех
“символов” с одинаковым набором букв (с одним именем) один и тот же object_id
.
Теперь взглянем на строки. Их object_id
не совпадает. Это означает, что это
два разных объекта в памяти. При создании строки Ruby всегда выделяет память для
нее.
Если вы сомневаетесь, что использовать - символ или строку - задумайтесь, что важнее: уникальность объекта (например, для ключа в хеше) или содержание (как в примере выше - “george”)
Все является объектом
“Все - это объект” - не преувеличение. Даже классы и числа, и с ними можно делать то, что и с обычными объектами:
Изменяемые константы
Константы на самом деле не константы. Если вы поменяете значение константы, это выдаст предупреждение, но не остановит программу. Однако это не говорит о том, что вы должны переопределять константы.
Соглашение о наименовании
Ruby диктует некоторые правила о наименовании. Константы начинаются с заглавной
буквы. Глобальные переменные начинаются со знака $
. Переменные экземпляра
начинаются с @
. Переменные класса начинаются с @@
.
Имена методов могут начинаться с заглавных букв, однако это может запутать, например:
Значение Constant
- 10, а Constant()
- 11.
Именованные параметры
Как и в Python, начиная с версии 2.0 Ruby методы принимают именованные параметры.
“Истинное” Ruby
В Ruby все кроме nil и false рассматриваются как истина. В С, Python и многих других языках 0 и некоторые другие значения, например пустой список, являются ложью. Взгляните на следующий код Python (пример применим и у другим языкам):
Это выведет на экран “0 - ложь”. Эквивалент на Ruby:
Выведет на экран “0 - истина”.
Модификаторы доступа действуют до конца контекста
В следующем Ruby коде
можно подумать, что another_method
публичный. Нет, это не так. Модификатор
доступа private
действует до конца контекста, или до другого модификатора
доступа. По умолчанию все методы публичны.
public
, private
и protected
на самом деле методы, и они могут принимать
параметры. Можно передать им имена методов как символы, чтобы поменять область
доступа метода.
Вызов методов
В Java public
означает, что метод можно вызвать везде. protected
методы можно
вызвать только инстансами этого класса, инстансами дочернего класса и инстансами
классов этого же пакета. private
методы не может вызвать никто кроме инстанса
класса.
В Ruby все немного по-другому. public
методы на самом деле публичные. private
метод может быть вызван только без явного объявления вызывающей стороны.
Только self может быть вызывающей стороной приватного метода.
О protected
методах надо поговорить подробнее. Protected метод может быть вызван
инстансом текущего или дочернего класса, однако может иметь вызывающей стороной
другой инстанс. Пример, позаимствованный из Ruby Language FAQ:
Открытые классы
Классы в Ruby “открыты”. То есть, вы можете открыть их и добавить или изменить их
в любое время. Даже базовые классы, такие как Integer
или Object
, родительский
для всех объектов. Ruby on Rails определяет несколько методов на Integer
, чтобы
работать со временем. Смотрите:
Прикольные имена методов
В Ruby имена методов могут оканчиваться на вопросительный или восклицательный
знаки. По соглашению методы, которые отвечают на вопрос, заканчиваются вопросительным
знаком (например, Array#empty?
возвращает true если массив пустой).
Некоторые, “потенциально опасные” методы (которые меняют вызывающую сторону, self
или параметры) заканчиваются восклицательным знаком (например, exit!
). Однако не
все методы, которые меняют аргументы заканчиваются так, например Array#replace
заменяет содержимое массива переданным массивом. Просто нет смысла иметь метод,
который бы не менял исходный массив в этом случае.
Singleton методы
Singleton методы - это методы, определенные на единственном инстансе и доступные только на нем.
“Пропавшие” методы
Ruby не сдается, если не находит вызванный метод, а вызывает метод method_missing
,
передав ему имя “потерянного” метода и аргументы. По умолчанию method_missing
вызывает исключение NameError, но вы можете переопределить его по вашим потребностям,
что и делает множество библиотек, например:
Пример выше просто выводит на экран детали вызова метода, но вы можете сделать что-то полезное по вашему усмотрению.
Передача сообщений, а не вызов функций
На самом деле вызов метода - это передача (send) ему сообщения. Наглядно:
Блоки - тоже объекты, только они об этом еще не знают
Блоки (на самом деле - замыкания) часто используются в стандартной библиотеке.
Чтобы вызвать блок можно либо использовать yield
, либо сделать его объектом
класса Proc
, прибавив специальный аргумент к списку аргументов, например так:
Вы можете создавать блоки-объекты также через Proc.new
с блоком или вызывая
lambda
метод.
В принципе, методы - это тоже объекты:
Операторы - это синтаксический сахар
Большинство операторов в Ruby - это просто синтаксический сахар (с учетом некоторых
правил) для вызова методов. Например, можно переопределить +
метод для класса
Integer
:
Так что вам не потребуется operator+
из С++, и т.д.
А еще можно симулировать обращения к объекту как к массиву с помощью методов []
и
[]=
. Можно определить унарные операторы + и - (например +1 или -2) методами +@
и -@
соответственно. Операторы ниже, однако, не являются синтаксическим сахаром.
Они не являются методами и не могут быть переопределены:
В дополнение к этому, +=
, *=
и т.д. - это всего лишь сокращения для
var = var + other_var
, var = var * other_var
и т.д. и, соответственно,
не могут быть переопределены.
Узнать больше
Если вам хочется узнать о Ruby больше - перейдите к документации.