Copy Semantics
Part of the Object Oriented Programming section of Coddy's R journey. Lesson 39 of 57.
S3 and S4 objects are values: a function that changes one changes its own copy. RC objects are references: the caller's object changes. The same function behaves differently for the two kinds:
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)Output:
1 2$copy() creates a new, independent object with the same field values. Changing the copy leaves the original alone:
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)Output:
0 100A list can hold the same RC object several times. Changing one element then changes all of them. Create a new object per element when they must be independent:
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)Output:
5 0identical(a, b) is TRUE for two names of the same RC object, and FALSE for a copy, even while the fields are still equal:
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)Output:
TRUE FALSE TRUEChallenge
EasyA text editor keeps save points. Declare the Reference Class Document in Document.R with the field text (character) and a method type(s) that appends s to the text. Then write checkpoint(doc), which returns an independent copy of the document.
The definition with methods is wrapped in suppressMessages(). The supplied code starts with a save point, then reads commands: save stores checkpoint(doc), undo goes back to a copy of the last save point, and any other line is typed. It prints the text and the saved text after each command, so a save point must never change when typing continues.
Your code goes in Document.R. main.R holds the supplied input/output code and cannot be edited.
Try it yourself
source("Document.R")
# Supplied input/output code: keep it as it is
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 = "")
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1S3 Basics
Working With FilesLists With a ClassConstructor FunctionsPrint and Format MethodsValidators and HelpersRecap - Temperatures4Encapsulation in R
Closures as ObjectsEnvironments as ObjectsAccessor FunctionsGuarding StateRecap - Parking Meter2S3 Generics and Methods
Generics and UseMethodDefault MethodsMethods for Base GenericsNextMethod BasicsRecap - Shape Areas8Reference Classes
Defining Reference ClassesMethods and Field UpdatesCopy SemanticsInheritance and callSuperRecap - Task Queue11Project: Library Management
Books and MembersBorrowing BooksPractice on your own: Online R compiler