Программирование на языке Ruby
Шрифт:
Модификатор доступа
protected
налагает меньше ограничений. Защищенные методы доступны только экземплярам того класса, в котором определены, и его подклассов. Для защищенного метода разрешается указывать вызывающий объект, так что к ним можно обращаться из других объектов (при условии, что вызывающий и вызываемый объекты принадлежат одному классу). Обычно защищенные методы применяются для определения методов доступа, чтобы два объекта одного типа могли взаимодействовать. В следующем примере объекты класс Person
можно сравнивать по возрасту, но сам возраст недоступен вне класса Person
:
class Person
def initialize(name, age)
@name, @age = name, age
end
def <=>(other)
age <=> other.age
end
attr_reader :name, :age
protected :age
end
p1 = Person.new("fred", 31)
p2 = Person.new("agnes", 43)
compare = (p1 <=> p2) # -1
x = p1.age #
Ошибка!
Чтобы завершить картину, модификатор
public
делает метод открытым. Неудивительно!.. И последнее: методы, определенные вне любого класса и модуля (то есть на верхнем уровне программы), по умолчанию закрыты. Поскольку они определены в классе
Object
, то видимы глобально, но обращаться к ним с указанием вызывающего объекта нельзя. 11.1.9. Копирование объектов
Встроенные методы
Object#clone
и #dup
порождают копию вызывающего объекта. Различаются они объемом копируемого контекста. Метод #dup
копирует только само содержимое объекта, тогда как clone
сохраняет и такие вещи, как синглетные классы, ассоциированные с объектом.
s1 = "cat"
def s1.upcase
"CaT"
end
s1_dup = s1.dup
s1_clone = s1.clone
s1 #=> "cat"
s1_dup.upcase #=> "CAT" (синглетный метод не копируется)
s1_clone.upcase #=> "СаТ" (используется синглетный метод)
И
dup
, и clone
выполняют поверхностное копирование, то есть копируют лишь содержимое самого вызывающего объекта. Если вызывающий объект содержит ссылки на другие объекты, то последние не копируются — копия будет ссылаться на те же самые объекты. Проиллюстрируем это на примере. Объект arr2
— копия arr1
, поэтому изменение элемента целиком, например arr2[2]
, не оказывает влияния на arr1
. Но исходный массив и его копия содержат ссылку на один и тот же объект String
, поэтому изменение строки через arr2
приведет к такому же изменению значения, на которое ссылается arr1
.
arr1 = [ 1, "flipper", 3 ]
arr2 = arr1.dup
arr2[2] = 99
arr2[1][2] = 'a'
arr1 # [1, "flapper", 3]
arr2 # [1, "flapper", 99]
Иногда
Самый «чистый» способ — потребовать, чтобы классы реализовывали метод
deep_copy
. Он мог бы рекурсивно обходить все объекты, на которые ссылается исходный объект, и вызывать для них метод deep_copy
. Необходимо было бы еще добавить метод deep_copy
во все встроенные классы Ruby, которыми вы пользуетесь. Но есть и более быстрый способ с использованием модуля
Marshal
. Если вы сериализуете исходный объект, представив его в виде строки, а затем загрузите в новый объект, то этот новый объект будет копией исходного.
arr1 = [ 1, "flipper", 3 ]
arr2 = Marshal.load(Marshal.dump(arr1))
arr2[2] = 99
arr2[1][2] = 'a'
arr1 # [1, "flipper", 3]
arr2 # [1, "flapper", 99]
Обратите внимание, что изменение строки через
arr2
не отразилось на строке, на которую ссылается arr1
. 11.1.10. Метод initialize_copy
При копировании объекта методом
dup
или clone
конструктор не вызывается. Копируется вся информация о состоянии. Но что делать, если вам такое поведение не нужно? Рассмотрим пример:
class Document
attr_accessor :title, :text
attr_reader :timestamp
def initialize(title, text)
@title, @text = title, text
@timestamp = Time.now
end
end
doc1 = Document.new("Random Stuff",File.read("somefile"))
sleep 300 # Немного подождем...
doc2 = doc1.clone
doc1.timestamp == doc2.timestamp # true
# Оп... временные штампы одинаковы!
При создании объекта
Document
с ним ассоциируется временной штамп. При копировании объекта копируется и его временной штамп. А как быть, если мы хотим запомнить время, когда было выполнено копирование?
Поделиться:
Популярные книги
На границе империй. Том 10. Часть 3
Вселенная EVE Online
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
Запечатанный во тьме. Том 3
3. Хроники Арнея
Фантастика:
уся
эпическая фантастика
фэнтези
5.00
рейтинг книги
Я снова князь. Книга XXIII
23. Дорогой барон!
Фантастика:
юмористическое фэнтези
аниме
попаданцы
5.00
рейтинг книги
Лекарь Империи 7
7. Лекарь Империи
Фантастика:
городское фэнтези
аниме
боевая фантастика
попаданцы
5.00
рейтинг книги
(Не)свободные, или Фиктивная жена драконьего военачальника
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Запечатанный во тьме. Том 2
2. Хроники Арнея
Фантастика:
уся
эпическая фантастика
фэнтези
5.00
рейтинг книги
Бояръ-Аниме. Газлайтер. Том 33
33. История Телепата
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 9
9. Лекарь
Фантастика:
боевая фантастика
юмористическое фэнтези
6.00
рейтинг книги
Тринадцатый XII
12. Видящий смерть
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
7.00
рейтинг книги
Телохранитель Генсека. Том 2
2. Медведев
Фантастика:
попаданцы
альтернативная история
6.25
рейтинг книги
Кодекс Охотника. Книга XXXVI
36. Кодекс Охотника
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Лекарь Империи 10
10. Лекарь Империи
Фантастика:
городское фэнтези
боевая фантастика
аниме
попаданцы
5.00
рейтинг книги
Инженер Петра Великого
1. Инженер Петра Великого
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Великий и Ужасный - 2
2. Великий и Ужасный
Фантастика:
киберпанк
городское фэнтези
попаданцы
5.00