Menu
Coddy logo textTech

Methods for Built-ins

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

setMethod() also adds S4 methods to base functions such as length() and summary(). The base function keeps working for everything else, and your class gets its own behaviour:

setClass("Playlist", slots = c(name = "character", songs = "character"))
setMethod("length", "Playlist", function(x) length(x@songs))
pl <- new("Playlist", name = "gym", songs = c("a", "b", "c"))
print(length(pl))
print(length(c(1, 2)))

Output:

[1] 3
[1] 2

Operators are generics too. A method for + names the classes of both sides in a signature(). The two arguments are called e1 and e2:

setClass("Money", slots = c(amount = "numeric"))
setMethod("show", "Money", function(object) cat(sprintf("%.2f", object@amount), "\n"))
setMethod("+", signature("Money", "Money"), function(e1, e2) {
  new("Money", amount = e1@amount + e2@amount)
})
new("Money", amount = 2.5) + new("Money", amount = 4)

Output:

6.50 

The group generic Arith stands for +, -, *, /, ^ and the rest at once. Inside its method, callGeneric() repeats whichever operator was used, on the values you pass:

setClass("Money", slots = c(amount = "numeric"))
setMethod("Arith", signature("Money", "numeric"), function(e1, e2) {
  new("Money", amount = callGeneric(e1@amount, e2))
})
m <- new("Money", amount = 10)
cat((m * 3)@amount, (m / 4)@amount, (m - 1)@amount)

Output:

30 2.5 9

The group generic Compare covers ==, <, > and the others. Its method returns what callGeneric() returns for the slots, a logical value:

setClass("Money", slots = c(amount = "numeric"))
setMethod("Compare", signature("Money", "Money"), function(e1, e2) {
  callGeneric(e1@amount, e2@amount)
})
a <- new("Money", amount = 5)
b <- new("Money", amount = 8)
cat(a < b, a == b, a >= b)

Output:

TRUE FALSE FALSE
challenge icon

Challenge

Easy

The class Money in Money.R has the slots amount (numeric) and currency (character). Add four methods:

  • show() prints 12.50 EUR and a new line;
  • + for two Money objects returns their sum, or stops with cannot add EUR and USD (use call. = FALSE) when the currencies differ;
  • * for Money and a number returns the scaled amount;
  • == for two Money objects is TRUE when amount and currency are both equal.

The supplied code reads lines 10:EUR + 2.5:EUR, 4:USD * 3 or 1:EUR == 1:EUR and prints the result or error: and the message.

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")))
parse_money <- function(t) {
  p <- strsplit(t, ":")[[1]]
  new("Money", amount = as.numeric(p[1]), currency = p[2])
}
for (line in input) {
  p <- strsplit(line, " ")[[1]]
  a <- parse_money(p[1])
  tryCatch({
    if (p[2] == "+") print(a + parse_money(p[3]))
    if (p[2] == "*") print(a * as.numeric(p[3]))
    if (p[2] == "==") cat(a == parse_money(p[3]), "\n", sep = "")
  }, error = function(e) cat("error: ", conditionMessage(e), "\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