Семантика копирования
Часть раздела Объектно-ориентированное программирование путешествия по R на Coddy. Урок 39 из 57.
Объекты S3 и S4 являются значениями: функция, которая изменяет один из них, изменяет свою собственную копию. Объекты RC являются ссылками: объект вызывающего кода изменяется. Одна и та же функция ведёт себя по-разному для этих двух типов:
setClass("S4Box", slots = c(n = "numeric"))
RCBox <- setRefClass("RCBox", fields = list(n = "numeric"))
bump_s4 <- function(b) { b@n <- b@n + 1; invisible(b) }
bump_rc <- function(b) b$n <- b$n + 1
v <- new("S4Box", n = 1)
r <- RCBox$new(n = 1)
bump_s4(v)
bump_rc(r)
cat(v@n, r$n)Вывод:
1 2$copy() создаёт новый независимый объект с теми же значениями полей. Изменение копии не затрагивает оригинал:
Account <- setRefClass("Account", fields = list(balance = "numeric"))
a <- Account$new(balance = 100)
alias <- a
backup <- a$copy()
alias$balance <- 0
cat(a$balance, backup$balance)Вывод:
0 100Список может содержать один и тот же объект RC несколько раз. При изменении одного элемента изменяются все они. Создавайте новый объект для каждого элемента, если они должны быть независимыми:
Counter <- setRefClass("Counter", fields = list(n = "numeric"))
one <- Counter$new(n = 0)
same <- list(one, one, one)
same[[1]]$n <- 5
fresh <- lapply(1:3, function(i) Counter$new(n = 0))
fresh[[1]]$n <- 5
cat(same[[3]]$n, fresh[[3]]$n)Вывод:
5 0identical(a, b) равно TRUE для двух имён одного и того же объекта RC и FALSE для копии, даже если поля всё ещё равны:
Account <- setRefClass("Account", fields = list(balance = "numeric"))
a <- Account$new(balance = 100)
b <- a
c2 <- a$copy()
cat(identical(a, b), identical(a, c2), c2$balance == a$balance)Вывод:
TRUE FALSE TRUEЗадание
ЛегкоТекстовый редактор хранит точки сохранения. Объявите Reference Class Document в Document.R с полем text (character) и методом type(s), который добавляет s к тексту. Затем напишите checkpoint(doc), возвращающую независимую копию документа.
Определение с методами обёрнуто в suppressMessages(). Предоставленный код начинает с точки сохранения, затем считывает команды: save сохраняет checkpoint(doc), undo возвращается к копии последней точки сохранения, а любая другая строка вводится как текст. После каждой команды он выводит текст и сохранённый текст, поэтому точка сохранения никогда не должна изменяться при продолжении ввода.
Ваш код должен находиться в Document.R. В main.R содержится предоставленный код ввода/вывода, и его нельзя изменять.
Попробуйте сами
source("Document.R")
# Предоставленный код ввода/вывода: оставьте его как есть
input <- suppressWarnings(readLines(file("stdin")))
doc <- Document$new(text = "")
saved <- checkpoint(doc)
for (cmd in input) {
if (cmd == "save") {
saved <- checkpoint(doc)
} else if (cmd == "undo") {
doc <- checkpoint(saved)
} else {
doc$type(cmd)
}
cat(cmd, " -> [", doc$text, "] saved [", saved$text, "]\n", sep = "")
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы S3
Работа с файламиСписки с классомФункции-конструкторыМетоды print и formatВалидаторы и вспомогательные функцииПовторение — температуры4Инкапсуляция в R
Замыкания как объектыОкружения как объектыФункции доступаЗащита состоянияПовторение — парковочный счётчик7S4 Наследование
Расширение с помощью containscallNextMethodВиртуальные классыПроверка типов с помощью is()Повторение — смотритель зоопарка10Шаблоны проектирования, часть 2
Шаблон «Декоратор»Шаблон «Строитель»Шаблон «Состояние»Шаблон «Итератор»2Обобщённые функции и методы S3
Обобщённые функции и UseMethodМетоды по умолчаниюМетоды для базовых обобщённых функцийОсновы NextMethodПовторение — площади фигур5Классы S4
Определение классов S4Слоты и доступПроверка корректностиМетоды showПовторение — каталог товаров8Ссылочные классы
Определение ссылочных классовМетоды и обновление полейСемантика копированияНаследование и callSuperПовторение — очередь задач11Проект: Управление библиотекой
Книги и читателиВыдача книг3Наследование S3
Векторы классовПорядок поиска методовРасширение с помощью NextMethodПроверка с помощью inherits()Повторение — расчёт зарплаты сотрудниковПотренируйтесь самостоятельно: Онлайн-компилятор R