Menu
Coddy logo textTech

callNextMethod

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

Inside an S4 method, callNextMethod() calls the method of the parent class with the same arguments and returns its result. A child method builds on the parent's answer instead of repeating it:

setClass("Employee", slots = c(name = "character", salary = "numeric"))
setClass("Manager", contains = "Employee", slots = c(reports = "numeric"))
invisible(setGeneric("describe", function(x) standardGeneric("describe")))
setMethod("describe", "Employee", function(x) paste(x@name, "earns", x@salary))
setMethod("describe", "Manager", function(x) paste(callNextMethod(), "and manages", x@reports))
print(describe(new("Manager", name = "Ada", salary = 60000, reports = 4)))

Output:

[1] "Ada earns 60000 and manages 4"

It works for show() too: the child prints the parent's lines and then its own:

setClass("Employee", slots = c(name = "character"))
setClass("Manager", contains = "Employee", slots = c(reports = "numeric"))
setMethod("show", "Employee", function(object) cat("Employee:", object@name, "\n"))
setMethod("show", "Manager", function(object) {
  callNextMethod()
  cat("Reports:", object@reports, "\n")
})
new("Manager", name = "Ada", reports = 4)

Output:

Employee: Ada 
Reports: 4 

new() calls the generic initialize(). A method for it can fill in slots that are worked out from others. It calls callNextMethod(.Object, ...) first, so the normal setup and the validity check still happen:

setClass("Order", slots = c(prices = "numeric", total = "numeric"))
setMethod("initialize", "Order", function(.Object, ...) {
  .Object <- callNextMethod(.Object, ...)
  .Object@total <- sum(.Object@prices)
  .Object
})
o <- new("Order", prices = c(2.5, 4, 1))
print(o@total)

Output:

[1] 7.5

Like NextMethod() in S3, callNextMethod() chains through several levels, each class adding its part:

setClass("Ticket", slots = c(base = "numeric"))
setClass("Vip", contains = "Ticket")
setClass("Backstage", contains = "Vip")
invisible(setGeneric("price", function(t) standardGeneric("price")))
setMethod("price", "Ticket", function(t) t@base)
setMethod("price", "Vip", function(t) callNextMethod() * 2)
setMethod("price", "Backstage", function(t) callNextMethod() + 50)
cat(price(new("Ticket", base = 30)), price(new("Vip", base = 30)), price(new("Backstage", base = 30)))

Output:

30 60 110
challenge icon

Challenge

Easy

Tickets come in three levels, each in its own file. The classes and the generic price() are declared. Add the methods:

  • Ticket.R: price() is the base price; show() prints Ticket for gala and a new line.
  • Vip.R: price() is 1.5 times the ticket price; show() prints the ticket line and then VIP lounge access.
  • Backstage.R: price() is the VIP price plus 50; show() prints the VIP lines and then Backstage pass.

Use callNextMethod() in the subclass methods. The supplied code reads lines vip gala 80 (level, event, base price) and prints each ticket and its price.

Your code goes in Ticket.R, Vip.R and Backstage.R. main.R holds the supplied input/output code and cannot be edited.

Try it yourself

source("Ticket.R")
source("Vip.R")
source("Backstage.R")

# Supplied input/output code: keep it as it is
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  p <- strsplit(line, " ")[[1]]
  base <- as.numeric(p[3])
  t <- switch(p[1],
    standard = new("Ticket", event = p[2], base = base),
    vip = new("VipTicket", event = p[2], base = base),
    backstage = new("BackstageTicket", event = p[2], base = base))
  print(t)
  cat(sprintf("price: %.2f", price(t)), "\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