Ruby: Всё есть объект

Ruby по своим возможностям и подходам в разработке близок к JavaScript и Python, но имеет свои особенности. Разработчики языка во многом опирались на Smalltalk, Lisp (это семейство языков), Perl и другие подобные языки. Это привело к интересному результату. Во-первых, Ruby — очень объектно-ориентированный язык. В Ruby всё есть объект, включая nil (это аналог null), и каждая операция — это вызов метода:

'hexlet'.reverse # telxeh
1.7.round # 2
nil.to_i # 0
1 + 1 # на самом деле 1.+(1)

Одна из сильных сторон Ruby – стандартная библиотека. Она решает практически все возникающие задачи. В одних только строках 185 встроенных методов!

Это одна из причин, почему Ruby чаще других выигрывает в CodeBattle

# Количество методов у разных типов данных
# В примерах ниже вызывается метод methods,
# хотя кажется, что это обращение к свойству
''.methods.count # 185
1.methods.count # 145
[].methods.count # 191

В Ruby всё, кроме присваивания, это вызовы методов. Такой подход позволяет переопределять буквально любое поведение:

# То, что на самом деле происходит, когда мы выполняем «операции»
1.+(5) # 6
1.>(3) # false

На этом основано очень много кода, особенно библиотечного. Например, у любого объекта можно определить синтаксис, аналогичный доступу к массиву []. Или можно определить операции для дат, сделав работу с ними максимально простой (как в примере прошлого урока). А вот как выглядят сеттеры у объектов:

# Кажется, что это прямое изменение свойства
# На самом деле это сеттер object.key=('value')
obj.key = 'value'

Все данные в Ruby — это объекты. Например nil, представлен классом NilClass, и является единственным его объектом. true — объект класса TrueClass, а false — объект класса FalseClass. У остальных типов свои классы.

Узнать класс любого объекта можно так:

1.class # Integer
''.class # String
nil.class # NilClass

С другой стороны, классы в Ruby — тоже объекты, у которых есть свои классы 0_o. Но это уже совсем другая история) Есть даже такая шутка (но это не шутка): в Ruby объект это класс, а класс — это объект. Почему это так – узнаем чуть позже.

Отладочная печать

Иногда в работе приходится прибегать к отладочной печати и в Ruby есть несколько особенностей, о которых надо знать. Функция put() выводит любые типы данных без необходимости преобразования их в строку. С другой стороны, такой вывод не останавливает выполнение и иногда это неудобно, если хочется посмотреть только первый вывод. Для таких ситуаций лучше использовать выброс исключения, которое и выведет на экран нужную информацию и прервет выполнение. Делается это так:

# raise – бросить исключение
# .inspect – метод, который преобразует любые данные в строковое представление
raise something.inspect

Задание

Напечатайте на экран следующий вызов:

# Здесь выводятся на экран все методы строк,
# которые содержат знак вопроса в имени
# Фактически — это вывод списка предикатов
# То же самое можно сделать для любого типа
puts 'hexlet'.methods.grep(/\?/)
# Будет выведено около 20 имен

Нашли ошибку? Есть что добавить? Пулреквесты приветствуются https://github.com/hexlet-basics
Если вы столкнулись с трудностями и не знаете, что делать, задайте вопрос в нашем большом и дружном сообществе