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] 2Operators 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 9The 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 FALSEChallenge
EasyThe class Money in Money.R has the slots amount (numeric) and currency (character). Add four methods:
show()prints12.50 EURand a new line;+for twoMoneyobjects returns their sum, or stops withcannot add EUR and USD(usecall. = FALSE) when the currencies differ;*forMoneyand a number returns the scaled amount;==for twoMoneyobjects isTRUEwhen 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 = ""))
}
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 Books3S3 Inheritance
Class VectorsMethod Lookup OrderExtending With NextMethodChecking With inherits()Recap - Staff Payroll6S4 Generics and Methods
Creating GenericsMethods for Built-insDispatch on Two ArgumentssetValidity and validObjectRecap - Money and CurrencyPractice on your own: Online R compiler