Menu
Coddy logo textTech

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] 9

The 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] 20

Inside 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] 1
challenge icon

Challenge

Easy

Complete the Reference Class Stack in Stack.R. It keeps its items in the field items (character, top last) and has four methods:

  • push(x) adds x on top and returns invisible(.self), so pushes can be chained;
  • pop() removes and returns the top item, or returns nothing when the stack is empty;
  • peek() returns the top item without removing it, or nothing;
  • 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 = "")
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