Кстати, если метод initialize_copy
пуст, то поведение будет такое же, как если бы он не был определен вовсе.
11.1.11. Метод allocate
Редко, но бывает, что нужно создать объект, не вызывая его конструктор (в обход метода initialize
). Например, может статься, что состояние объекта полностью определяется методами доступа к нему; тогда не нужно вызывать метод new
(который вызовет initialize
), разве что вы сами захотите это сделать. Представьте, что для инициализации состояния объекта вы собираете данные по частям: начать следует с «пустого» объекта, а не получить все данные заранее, а потом вызвать конструктор.
Метод allocate
появился в версии Ruby 1.8, чтобы упростить решение этой задачи. Он возвращает «чистый», еще не инициализированный объект класса.
class Person
attr_accessor :name, :age, :phone
def initialize(n,a,p)
@name, @age, @phone = n, a, p
end
end
p1 = Person.new('John Smith',29,'555-1234')
p2 = Person.allocate
p p1.age # 29
p p2.age # nil
11.1.12. Модули
Для использования модулей в Ruby есть две основных причины. Первая — облегчить управление пространством имен; если поместить константы и методы в модули, то будет меньше конфликтов имен. Хранящийся таким образом метод (метод модуля) вызывается с указанием имени модуля, то есть без вызывающего объекта. Точно так же вызывается и метод класса. Увидев вызовы вида File.ctime
или FileTest.exist?
, мы не можем определить по контексту, что File
— это класс, а FileTest
— модуль.
Вторая причина более интересна: мы можем использовать модуль как примесь.
Мы уже говорили о методах модуля, а как насчет методов экземпляра? Модуль — это не класс, у него не может быть экземпляров, а к методу экземпляра нельзя обратиться, не указав вызывающий объект.
Но оказывается, модуль может иметь методы экземпляра. Они становятся частью класса, который включил модуль директивой include
.
module MyMod
def meth1
puts 'Это метод 1.'
end
end
class MyClass
include MyMod
# ...
end
x = MyClass.new
x.meth1 # Это метод 1.
Здесь модуль MyMod
подмешан к классу MyClass
, а метод экземпляра meth1
унаследован. Вы видели также, как директива include
употребляется на верхнем уровне программы; в таком случае модуль подмешивается к классу Object
.
А что происходит с методами модуля, если таковые определены? Если вы думаете, что они становятся методами класса, то ошибаетесь. Методы модуля не подмешиваются.
Но если такое поведение желательно, то его можно реализовать с помощью нехитрого трюка. Существует метод append_features
, который можно переопределить. Он вызывается с параметром — «целевым» классом или модулем (в который включается данный модуль). Пример приведен в листинге 11.6.
module MyMod
def MyMod.append_features(someClass)
def someClass.modmeth
puts 'Метод модуля (класса) '
end
super # Этот вызов обязателен!
end
def meth1
puts 'Метод 1'
end
end
class MyClass
include MyMod
def MyClass.classmeth
puts 'Метод класса'
end
def meth2
puts 'Метод 2'
end