Slots and Access
Part of the Object Oriented Programming section of Coddy's R journey. Lesson 23 of 57.
obj@slot <- value changes a slot. Like S3 objects, S4 objects are values: a function that changes one works on its own copy and returns it:
setClass("Person", slots = c(name = "character", age = "numeric"))
birthday <- function(p) {
p@age <- p@age + 1
p
}
ada <- new("Person", name = "Ada", age = 36)
older <- birthday(ada)
cat(ada@age, older@age)Output:
36 37slot(obj, "name") does the same as @ with the slot name in a string, so it works with a name held in a variable. slotNames() lists the slots of a class or object:
setClass("Person", slots = c(name = "character", age = "numeric"))
ada <- new("Person", name = "Ada", age = 36)
for (s in slotNames(ada)) cat(s, "=", format(slot(ada, s)), "\n")
slot(ada, "age") <- 37
print(ada@age)Output:
name = Ada
age = 36
[1] 37Every assignment is checked against the declared type, not only new(). A wrong value is refused and the object keeps its old one:
setClass("Person", slots = c(name = "character", age = "numeric"))
ada <- new("Person", name = "Ada", age = 36)
ada@age <- "old"Output:
Error in (function (cl, name, valueClass) :
assignment of an object of class “character” is not valid for @‘age’ in an object of class “Person”; is(value, "numeric") is not TRUE
Execution haltedgetSlots() returns every slot name with its declared type, which lets code convert text input to the type a slot expects:
setClass("Person", slots = c(name = "character", age = "numeric"))
types <- getSlots("Person")
print(types)
value <- "40"
if (types[["age"]] == "numeric") value <- as.numeric(value)
print(value + 1)Output:
name age
"character" "numeric"
[1] 41Challenge
EasyThe class Profile in Profile.R has the slots name and city (character) and age (numeric). Complete two functions:
update_profile(p, field, value)stops withno field email(usecall. = FALSE) when the field is not a slot; otherwise it converts the textvaluewithas.numeric()when the slot is numeric, sets the slot withslot()and returns the changed profile.profile_lines(p)returns one line per slot, in slot order:name: Ada.
The supplied code reads a name, then lines city=Paris or age=36, applies each, and prints the profile's lines.
Your code goes in Profile.R. main.R holds the supplied input/output code and cannot be edited.
Try it yourself
source("Profile.R")
# Supplied input/output code: keep it as it is
input <- suppressWarnings(readLines(file("stdin")))
p <- new("Profile", name = input[1], city = "unknown", age = 0)
for (line in input[-1]) {
kv <- strsplit(line, "=")[[1]]
p <- tryCatch(update_profile(p, kv[1], kv[2]), error = function(e) {
cat("error: ", conditionMessage(e), "\n", sep = "")
p
})
}
for (l in profile_lines(p)) cat(l, "\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