Чтение онлайн

на главную - закладки

Жанры

Программирование на языке Ruby
Шрифт:

Для этого нужно определить метод

initialize_copy
. Он вызывается как раз при копировании объекта. Этот метод аналогичен
initialize
и позволяет полностью контролировать состояние объекта.

class Document # Определяем новый метод в классе.

 def initialize_copy(other)

@timestamp = Time.now

 end

end

doc3 = Document.new("More Stuff", File.read("otherfile"))

sleep 300 # Немного подождем...

doc4 = doc3.clone

doc3.timestamp == doc4.timestamp # false

# Теперь временные штампы правильны.

Отметим, что метод

initialize_copy
вызывается после того, как вся информация скопирована. Поэтому мы и опустили строку:

@title, @text = other.title, other.text

Кстати, если метод

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.

Листинг 11.6. Включение модуля с переопределенным методом append_features

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

end

x = MyClass.new

# Выводится:

MyClass.classmeth # Метод класса

x.meth1 # Метод 1

Поделиться:
Популярные книги

Вечный. Книга II

Рокотов Алексей
2. Вечный
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Вечный. Книга II

Газлайтер. Том 31

Володин Григорий Григорьевич
31. История Телепата
Фантастика:
боевая фантастика
попаданцы
альтернативная история
фэнтези
5.00
рейтинг книги
Газлайтер. Том 31

Ночной администратор

Ле Карре Джон
Детективы:
шпионские детективы
7.14
рейтинг книги
Ночной администратор

Наследник 2

Шимохин Дмитрий
2. Старицкий
Фантастика:
попаданцы
альтернативная история
фэнтези
5.75
рейтинг книги
Наследник 2

Эволюционер из трущоб. Том 2

Панарин Антон
2. Эволюционер из трущоб
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
Эволюционер из трущоб. Том 2

Неучтенный элемент. Том 2

NikL
2. Антимаг. Вне системы
Фантастика:
городское фэнтези
фэнтези
5.00
рейтинг книги
Неучтенный элемент. Том 2

Все, что шевелится

Федотов Сергей
Фантастика:
юмористическая фантастика
5.00
рейтинг книги
Все, что шевелится

Ярар. Начало

Грехов Тимофей
1. Ярар
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Ярар. Начало

Эволюционер из трущоб. Том 6

Панарин Антон
6. Эволюционер из трущоб
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Эволюционер из трущоб. Том 6

Сон для слабаков!

Дорничев Дмитрий
5. Моё пространственное убежище
Фантастика:
фэнтези
боевая фантастика
рпг
5.00
рейтинг книги
Сон для слабаков!

Нелюдь

Шелег Дмитрий Витальевич
1. Нелюдь
Фантастика:
фэнтези
8.87
рейтинг книги
Нелюдь

Герой

Мазин Александр Владимирович
4. Варяг
Фантастика:
альтернативная история
9.10
рейтинг книги
Герой

Последний Паладин. Том 4

Саваровский Роман
4. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 4

Я еще князь. Книга XX

Дрейк Сириус
20. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я еще князь. Книга XX