Необходимо оговориться, что операции load и require не имеют ничего общего с модулями: они относятся к исходным и двоичным файлам (загружаемым динамически или статически). Операция load читает файл и вставляет его в текущую точку исходного текста, так что начиная с этой точки становятся видимы все определения, находящиеся во внешнем файле. Операция require аналогична load, но не загружает файл, если он уже был загружен ранее.
Программисты, только начинающие осваивать Ruby, особенно имеющие опыт работы с языком С, могут поначалу путать операции require и include, которые никак не связаны между собой. Вы еще поймаете себя на том, что сначала вызываете require, а потом include для того, чтобы воспользоваться каким-то внешним модулем.
1.3.4. Создание классов
В Ruby есть множество встроенных классов, и вы сами можете определять новые. Для определения нового класса применяется такая конструкция:
class ClassName
# ...
end
Само имя класса - это глобальная константа, поэтому оно должно начинаться с прописной буквы. Определение класса может содержать константы, переменные класса, методы класса, переменные экземпляра и методы экземпляра. Данные уровня класса доступны всем объектам этого класса, тогда как данные уровня экземпляра доступны только одному объекту
Попутное замечание: строго говоря, классы в Ruby не имеют имен.Class (поскольку в Ruby Class — это класс). Ясно, что на один и тот же класс могут ссылаться несколько констант, и их можно присваивать переменным точно так же, как мы поступаем с любыми другими объектами (поскольку в Ruby Class — это объект). Если вы немного запутались, не расстраивайтесь. Удобства ради новичок может считать, что в Ruby имя класса — то же самое, что в C++.
Вот как определяется простой класс:
class Friend
@@myname = "Эндрю" # переменная класса
def initialize(name, sex, phone)
@name, @sex, @phone = name, sex, phone
# Это переменные экземпляра
end
def hello # метод экземпляра
puts "Привет, я #{@name}."
end
def Friend.our_common_friend # метод класса
puts "Все мы друзья #{@@myname}."
end
end
f1 = Friend.new("Сюзанна","F","555-0123")
f2 = Friend.new("Том","M","555-4567")
f1.hello # Привет, я Сюзанна.
f2.hello # Привет, я Том.
Friend.our_common_friend # Все мы друзья Эндрю.
Поскольку данные уровня класса доступны во всем классе, их можно инициализировать в момент определения класса. Если определен метод с именем initialize, то гарантируется, что он будет вызван сразу после выделения памяти для объекта. Этот метод похож на традиционный конструктор, но не выполняет выделения памяти. Память выделяется методом new, а освобождается неявно сборщиком мусора.
Теперь взгляните на следующий фрагмент, обращая особое внимание на методы getmyvar, setmyvar и myvar=:
class MyClass
NAME = "Class Name" # константа класса
@@count = 0 # инициализировать переменную класса
def initialize # вызывается после выделения памяти для объекта
@@count += 1
@myvar = 10
end
def MyClass.getcount # метод класса
@@count # переменная класса
end
def getcount # экземпляр возвращает переменную класса!
@@count # переменная класса
end
def getmyvar # метод экземпляра
@myvar # переменная экземпляра
end
def setmyvar(val) # метод экземпляра устанавливает @myvar
@myvar = val
end
def myvar=(val) # другой способ установить @myvar
@myvar = val
end
end
foo = MyClass.new # @myvar равно 10
foo.setmyvar 20 # @myvar равно 20
foo.myvar =30 # @myvar равно 30