Print and Format Methods
Part of the Object Oriented Programming section of Coddy's R journey. Lesson 4 of 57.
When a value is printed, R calls the function print(). Without anything special for the class, an S3 object prints as its list followed by the class attribute, which is hard to read:
m <- structure(list(amount = 9.5, currency = "EUR"), class = "money")
print(m)Output:
$amount
[1] 9.5
$currency
[1] "EUR"
attr(,"class")
[1] "money"A method is a function named generic.class. When print() gets an object of class money, it looks for print.money() and calls it instead. A print method writes with cat() and ends with invisible(x), so it returns the object without printing it a second time:
print.money <- function(x, ...) {
cat("<money ", x$amount, " ", x$currency, ">\n", sep = "")
invisible(x)
}
m <- structure(list(amount = 9.5, currency = "EUR"), class = "money")
print(m)
mOutput:
<money 9.5 EUR>
<money 9.5 EUR>format() is the generic for turning a value into text. A format.money() method returns the text instead of printing it, so other code can put it into a sentence, and the print method can reuse it:
format.money <- function(x, ...) {
sprintf("%.2f %s", x$amount, x$currency)
}
print.money <- function(x, ...) {
cat("Money:", format(x), "\n")
invisible(x)
}
m <- structure(list(amount = 9.5, currency = "EUR"), class = "money")
m
cat("You owe", format(m), "\n")Output:
Money: 9.50 EUR
You owe 9.50 EUR A method takes the same arguments as its generic. print() and format() are declared as function(x, ...), so their methods start with x, ... too. The ... accepts extra arguments such as digits that a caller may pass. Methods work wherever the generic is called, for example inside vapply():
format.money <- function(x, ...) sprintf("%.2f %s", x$amount, x$currency)
wallet <- list(
structure(list(amount = 3, currency = "EUR"), class = "money"),
structure(list(amount = 0.5, currency = "USD"), class = "money")
)
print(vapply(wallet, format, character(1)))Output:
[1] "3.00 EUR" "0.50 USD"Challenge
Easynew_money() in Money.R is given. Add two methods to the same file:
format.money(x, ...)returns the amount with two decimal places and the currency:9.50 EUR.print.money(x, ...)prints<money 9.50 EUR>on its own line, usingformat(), and returnsinvisible(x).
The supplied code reads lines 9.5 EUR, prints every money object, then prints list: with all the formatted amounts joined by + .
Your code goes in Money.R. main.R holds the supplied input/output code and cannot be edited.
Try it yourself
source("Money.R")
# Supplied input/output code: keep it as it is
input <- suppressWarnings(readLines(file("stdin")))
all <- list()
for (line in input) {
p <- strsplit(line, " ")[[1]]
m <- new_money(as.numeric(p[1]), p[2])
print(m)
all[[length(all) + 1]] <- m
}
cat("list: ", paste(vapply(all, format, character(1)), collapse = " + "), "\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