Methods for Base Generics
Part of the Object Oriented Programming section of Coddy's R journey. Lesson 9 of 57.
Many functions in base R are S3 generics: print(), format(), summary(), toString(), length(), as.character() and more. Adding a method makes your class work with a function every R user already knows. summary.gradebook() reports on a whole object:
summary.gradebook <- function(object, ...) {
paste0(length(object$marks), " marks, average ", mean(object$marks))
}
g <- structure(list(marks = c(70, 85, 91)), class = "gradebook")
cat(summary(g), "\n")Output:
3 marks, average 82 Check the generic's parameters before you write the method: summary() calls its first argument object, while toString() and format() call it x. toString() should return a single string:
toString.gradebook <- function(x, ...) paste(x$marks, collapse = " / ")
g <- structure(list(marks = c(70, 85, 91)), class = "gradebook")
print(toString(g))Output:
[1] "70 / 85 / 91"A length() method changes what length() means for the class. A queue that stores its items in a field can report how many items it holds, instead of the number of fields in the list:
q <- structure(list(items = c("a", "b", "c"), name = "jobs"), class = "queue")
print(length(q))
length.queue <- function(x) length(x$items)
print(length(q))Output:
[1] 2
[1] 3Operators are generics too. A method named "+.money", written with quotes because of the symbol, runs when either side of + is a money object. It receives the two sides as e1 and e2:
new_money <- function(amount) structure(list(amount = amount), class = "money")
"+.money" <- function(e1, e2) new_money(e1$amount + e2$amount)
"==.money" <- function(e1, e2) e1$amount == e2$amount
a <- new_money(5)
b <- new_money(7)
print((a + b)$amount)
print(a == b)Output:
[1] 12
[1] FALSEChallenge
EasyA stack keeps its items in the field items, with the top of the stack last. new_stack(), push() and pop() in Stack.R are given. Add three methods:
length.stack()returns the number of items.toString.stack()returns the items from top to bottom joined by|, orempty.summary.stack()returnsstack of 3, top: c, orstack of 0when it is empty.
The supplied code reads commands push <item> and pop, then prints the length, toString() and summary().
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 <- new_stack()
for (cmd in input) {
if (cmd == "pop") s <- pop(s) else s <- push(s, substring(cmd, 6))
}
cat("length: ", length(s), "\n", sep = "")
cat("items: ", toString(s), "\n", sep = "")
cat(summary(s), "\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