Methods and Field Updates
Part of the Object Oriented Programming section of Coddy's R journey. Lesson 38 of 57.
Methods go in the methods list of setRefClass(). Inside a method the fields are plain names, and <<- changes a field. On the Coddy runner, R prints a note about the optional codetools package when a class with methods is defined, so wrap the definition in suppressMessages():
Counter <- suppressMessages(setRefClass("Counter",
fields = list(count = "numeric"),
methods = list(
add = function(n = 1) {
count <<- count + n
},
report = function() paste("count is", count)
)
))
c1 <- Counter$new(count = 0)
c1$add()
c1$add(5)
print(c1$report())Output:
[1] "count is 6".self is the object the method was called on. A method that ends with invisible(.self) returns the object, so calls can be chained:
Counter <- suppressMessages(setRefClass("Counter",
fields = list(count = "numeric"),
methods = list(
add = function(n = 1) {
count <<- count + n
invisible(.self)
}
)
))
c1 <- Counter$new(count = 0)
c1$add(2)$add(3)$add(4)
print(c1$count)Output:
[1] 9The method initialize runs inside $new(). initFields(...) sets the fields that were passed in; afterwards the method can give defaults to the others. Methods call each other by name:
Account <- suppressMessages(setRefClass("Account",
fields = list(owner = "character", balance = "numeric"),
methods = list(
initialize = function(...) {
initFields(...)
if (length(balance) == 0) balance <<- 0
invisible(.self)
},
deposit = function(x) balance <<- balance + x,
deposit_twice = function(x) {
deposit(x)
deposit(x)
}
)
))
a <- Account$new(owner = "Ada")
a$deposit_twice(10)
print(a$balance)Output:
[1] 20Inside a method, a plain <- to a field name creates a local variable with that name and leaves the field unchanged. Use <<- for every change of a field:
Counter <- suppressMessages(setRefClass("Counter",
fields = list(count = "numeric"),
methods = list(
broken = function() count <- count + 1,
working = function() count <<- count + 1
)
))
c1 <- Counter$new(count = 0)
c1$broken()
c1$broken()
c1$working()
print(c1$count)Output:
[1] 1Challenge
EasyComplete the Reference Class Stack in Stack.R. It keeps its items in the field items (character, top last) and has four methods:
push(x)addsxon top and returnsinvisible(.self), so pushes can be chained;pop()removes and returns the top item, or returnsnothingwhen the stack is empty;peek()returns the top item without removing it, ornothing;size()returns the number of items.
The definition is wrapped in suppressMessages() already. The supplied code reads commands push a b, pop and peek, then pushes two more items in one chained call and prints the size.
Your code goes in Stack.R. main.R holds the supplied input/output code and cannot be edited.
Try it yourself
source("Stack.R")
# Supplied input/output code: keep it as it is
input <- suppressWarnings(readLines(file("stdin")))
s <- Stack$new()
for (cmd in input) {
if (startsWith(cmd, "push ")) {
items <- strsplit(substring(cmd, 6), " ")[[1]]
for (it in items) s$push(it)
} else if (cmd == "pop") {
cat("popped ", s$pop(), "\n", sep = "")
} else if (cmd == "peek") {
cat("top ", s$peek(), "\n", sep = "")
}
}
s$push("x")$push("y")
cat("size after two chained pushes: ", s$size(), "\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