myFile = File.new('textfile.txt','w')
myString = String.new('Это строковый объект')
Однако не всегда его обязательно вызывать явно. В частности, при создании объекта String можно и не упоминать этот метод:
yourString = 'Это тоже строковый объект'
aNumber =5 # и здесь метод new не нужен
Ссылки на объекты хранятся в переменных. Выше уже отмечалось, что сами переменные не имеют типа и не являются объектами — они лишь ссылаются на объекты.
x = 'abc'
Из этого правила есть исключение: небольшие неизменяемые объекты некоторых встроенных классов, например Fixnum
, непосредственно копируются в переменные, которые на них ссылаются. (Размер этих объектов не превышает размера указателя, поэтому хранить их таким образом более эффективно.) В таком случае во время присваивания делается копия объекта, а куча не используется.
При присваивании переменных ссылки на объекты обобществляются.
y = 'abc'
x = y
x # 'abc'
После выполнения присваивания x = y
и x
, и y
ссылаются на один и тот же объект:
x.object_id # 53732208
y.object_id # 53732208
Если объект изменяемый, то модификация, примененная к одной переменной, отражается и на другой:
x.gsub!(/а/, 'x')
y # 'хbс'
Однако новое присваивание любой из этих переменных не влияет на другую:
# Продолжение предыдущего примера
x = 'abc'
y # по-прежнему равно 'хbс'
Изменяемый объект можно сделать неизменяемым, вызвав метод freeze
:
x.freeze
x.gsub!(/b/,'y') # Ошибка!
Символ в Ruby ссылается на переменную по имени, а не по ссылке. Во многих случаях он может вообще не ссылаться на идентификатор, а вести себя как некая разновидность неизменяемой строки. Символ можно преобразовать в строку с помощью метода to_s
.
Hearts = :Hearts # Это один из способов присвоить
Clubs = :Clubs # уникальное значение константе,
Diamonds = :Diamonds # некий аналог перечисления
Spades = :Spades # в языках Pascal или С.
puts Hearts.to_s # Печатается 'Hearts'
Продемонстрированный выше фокус с «перечислением» был более осмыслен на ранних этапах развития Ruby, когда еще не было класса Symbol
, а наличие двоеточия перед идентификатором превращало его в целое число. Если вы пользуетесь таким трюком, не предполагайте, что фактическое значение символа будет неизменным или предсказуемым - просто используйте его как константу, значение которой неважно.
1.3.3. Модули и классы-примеси
Многие встроенные методы наследуются от классов-предков. Особо стоит отметить методы модуля Kernel
, подмешиваемые к суперклассу Object
. Поскольку класс Object
повсеместно доступен, то и добавленные в него из Kernel
методы также доступны в любой точке программы. Эти методы играют важную роль в Ruby.
Термины «модуль» и «примесь» — почти синонимы.include
). В таком случае он используется как
Этот термин очевидно заимствован из языка Python. Стоит отметить, что в некоторых вариантах LISP такой механизм существует уже больше двадцати лет.
Не путайте описанное выше употребление термина «модуль» с другим значением, которое часто придается ему в информатике. Модуль в Ruby — это не внешний исходный текст и не двоичный файл (хотя может храниться и в том, и в другом виде). Это объектно-ориентированная абстракция, в чем-то похожая на класс.
Примером использования модуля для управления пространством имен служит модуль Math
. Так, чтобы получить определение числа π, необязательно включать модуль Math
с помощью предложения include;
достаточно просто написать Math::PI
.
Примесь дает способ получить преимущества множественного наследования, не отягощенные характерными для него проблемами. Можно считать, что это ограниченная форма множественного наследования, но создатель языка Мац называет его одиночным наследованием с разделением реализации.
Отметим, что предложение include
включает имена из указанного пространства имен (модуля) в текущее. Метод extend
добавляет объекту функции из модуля. В случае применения include
методы модуля становятся доступны как методы экземпляра, а в случае extend
— как методы класса.
Необходимо оговориться, что операции load
и require
не имеют ничего общего с модулями: они относятся к исходным и двоичным файлам (загружаемым динамически или статически). Операция load
читает файл и вставляет его в текущую точку исходного текста, так что начиная с этой точки становятся видимы все определения, находящиеся во внешнем файле. Операция require
аналогична load
, но не загружает файл, если он уже был загружен ранее.
Программисты, только начинающие осваивать Ruby, особенно имеющие опыт работы с языком С, могут поначалу путать операции require
и include
, которые никак не связаны между собой. Вы еще поймаете себя на том, что сначала вызываете require
, а потом include
для того, чтобы воспользоваться каким-то внешним модулем.
1.3.4. Создание классов
В Ruby есть множество встроенных классов, и вы сами можете определять новые. Для определения нового класса применяется такая конструкция:
class ClassName
# ...
end