Добавить в цитаты Настройки чтения

Страница 24 из 53



• Аналогично метод класса ассоциирован с тем классом, в котором определен; он не принадлежит никакому конкретному объекту и не может вызываться от имени объекта. При вызове метода класса указывается имя класса, а при вызове метода экземпляра - имя объекта.

• В публикациях, посвященных Ruby, часто для обозначения метода экземпляра применяют решеточную нотацию. Например, мы пишем File.chmod, чтобы обозначить метод chmod класса File, и File#chmod для обозначения метода экземпляра с таким же именем. Эта нотация не является частью синтаксиса Ruby. Мы старались не пользоваться ей в этой книге.

• В Ruby константы не являются истинно неизменными. Их нельзя изменять в теле методов экземпляра, но из других мест это вполне возможно.

• Ключевое слово yield пришло из языка CLU и некоторым программистам может быть непонятно. Оно используется внутри итератора, чтобы передать управление блоку, с которым итератор был вызван. В данном случае yield не означает, что нужно получить результат или вернуть значение. Скорее, речь идет о том, чтобы уступить процессор для работы.

• Составные операторы присваивания +=, -= и пр. — это не методы (собственно, это даже не операторы). Это всего лишь «синтаксическая глазурь» или сокращенная форма записи более длинной формы. Поэтому x += y значит в точности то же самое, что x = x + y. Если оператор + перегружен, то оператор += «автоматически» учитывает новую семантику.

• Из-за того, как определены составные операторы присваивания, их нельзя использовать для инициализации переменных. Если первое обращение к переменной x выглядит как x += 1, возникнет ошибка. Это интуитивно понятно для программистов, если только они не привыкли к языку, в котором переменные автоматически инициализируются нулем или пустым значением.

• Такое поведение можно в некотором смысле обойти. Можно определить операторы для объекта nil, так что в случае, когда начальное значение переменной равно nil, мы получим желаемый результат. Так, метод nil.+, приведенный ниже, позволит инициализировать объект типа string или Fixnum, для чего достаточно вернуть аргумент other. Таким образом, nil + other будет равно other.

def nil.+(other)

 other

end

Мы привели этот код для иллюстрации возможностей Ruby, но стоит ли поступать так на практике, оставляем на усмотрение читателя.

• Уместно будет напомнить, что Class — это объект, a Object — это класс. Мы попытаемся прояснить этот вопрос в следующей главе, а пока просто повторяйте это как мантру.

• Некоторые операторы нельзя перегружать, потому что они встроены в сам язык, а не реализованы в виде методов. К таковым относятся =, .., ..., and, or, not, &&, ||, !, != и !~. Кроме того, нельзя перегружать составные операторы присваивания (+=, -= и т.д.). Это не методы и, пожалуй, даже не вполне операторы.

• Имейте в виду, что хотя оператор присваивания перегружать нельзя, тем не менее возможно написать метод экземпляра с именем fоо= (тогда станет допустимым предложение x.foo = 5). Можете рассматривать знак равенства как суффикс.

• Напомним: «голый» оператор разрешения области видимости подразумевает наличие Object перед собой, то есть ::Foo — то же самое, что Objеct::Foo.

• Как уже говорилось, fail — синоним raise.

• Напомним, что определения в Ruby исполняются. Вследствие динамической природы языка можно, например, определить два метода совершенно по-разному в зависимости от значения признака, проверяемого во время выполнения.

• Напомним, что конструкция for (for x in а) на самом деле вызывает итератор each. Любой класс, в котором такой итератор определен, можно обходить в цикле for.



• Не забывайте, что метод, определенный на верхнем уровне, добавляется в модуль Kernel и, следовательно, становится членом класса Object.

• Методы установки (например, fоо=) должны вызываться от имени объекта, иначе анализатор решит, что речь идет о присваивании переменной с таким именем.

• Напомним, что ключевое слово retry можно использовать в итераторах, но не в циклах общего вида. В контексте итератора оно заставляет заново инициализировать все параметры и возобновить текущую итерацию с начала.

• Ключевое слово retry применяется также при обработке исключений. Не путайте два этих вида использования.

• Метод объекта initialize всегда является закрытым.

• Когда итератор заканчивается левой фигурной скобкой (или словом end) и возвращает значение, это значение можно использовать для вызова последующих методов, например:

squares = [1,2,3,4,5].collect do |x| x**2 end.reverse

# squares теперь равно [25,16,9,4,1]

• В конце программы на Ruby часто можно встретить идиому

if $0 == __FILE__

Таким образом проверяется, исполняется ли файл как автономный кусок кода (true) или как дополнительный, например библиотека (false). Типичное применение — поместить некую «главную программу» (обычно с тестовым кодом) в конец библиотеки.

• Обычное наследование (порождение подкласса) обозначается символом <:

class Dog < Animal

 # ...

end

Однако для создания синглетного класса (анонимного класса, который расширяет единственный экземпляр) применяется символ <<: