Menu
Coddy logo textTech

Defining Reference Classes

Part of the Object Oriented Programming section of Coddy's R journey. Lesson 37 of 57.

Reference Classes (RC) are R's system for objects that change in place, as in Java or Python. setRefClass() declares a class with typed fields and returns a generator; $new() creates an object, and $ reads and changes its fields:

Account <- setRefClass("Account", fields = list(owner = "character", balance = "numeric"))
a <- Account$new(owner = "Ada", balance = 100)
a$balance <- a$balance + 50
cat(a$owner, a$balance)

Output:

Ada 150

An RC object is a reference, like an environment. Assigning it to another variable or passing it to a function does not copy it, so a change through any name is a change to the one object:

Account <- setRefClass("Account", fields = list(owner = "character", balance = "numeric"))
pay_fee <- function(acc) acc$balance <- acc$balance - 5
a <- Account$new(owner = "Ada", balance = 100)
b <- a
b$balance <- 60
pay_fee(a)
cat(a$balance, b$balance)

Output:

55 55

Fields are typed. Assigning a value of the wrong class is refused, and the field keeps its old value:

Account <- setRefClass("Account", fields = list(owner = "character", balance = "numeric"))
a <- Account$new(owner = "Ada", balance = 100)
msg <- tryCatch({ a$balance <- "lots"; "changed" }, error = function(e) conditionMessage(e))
cat(msg, "\n")
cat(a$balance, "\n")

Output:

invalid assignment for reference class field ‘balance’, should be from class “numeric” or a subclass (was class “character”) 
100 

The generator describes the class: Account$fields() lists the fields and their types. An object printed without a show method lists its fields; a field that was not given is empty:

Account <- setRefClass("Account", fields = list(owner = "character", balance = "numeric"))
print(Account$fields())
Account$new(owner = "Bo")

Output:

      owner     balance 
"character"   "numeric" 
Reference class object of class "Account"
Field "owner":
[1] "Bo"
Field "balance":
numeric(0)
challenge icon

Challenge

Easy

Declare the Reference Class Book in Book.R with the fields title and author (character) and pages (numeric), and keep the generator in Book. Then write add_pages(book, n), which adds n to the book's pages in place and returns nothing useful.

The supplied code reads title;author;pages, creates the book, gives it to a second variable, adds the remaining numbers through that second name, and prints the original book and the field names.

Your code goes in Book.R. main.R holds the supplied input/output code and cannot be edited.

Try it yourself

source("Book.R")

# Supplied input/output code: keep it as it is
input <- suppressWarnings(readLines(file("stdin")))
p <- strsplit(input[1], ";")[[1]]
b <- Book$new(title = p[1], author = p[2], pages = as.numeric(p[3]))
alias <- b
for (n in as.numeric(input[-1])) add_pages(alias, n)
cat(b$title, " by ", b$author, ": ", b$pages, " pages\n", sep = "")
cat("fields: ", paste(names(Book$fields()), collapse = ", "), "\n", sep = "")
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming

Practice on your own: Online R compiler