Class Vectors
Part of the Object Oriented Programming section of Coddy's R journey. Lesson 12 of 57.
S3 inheritance comes from the class vector. An object with class = c("manager", "employee") is a manager and also an employee. When a generic has no method for manager, dispatch moves on and uses the employee method:
pay <- function(x) UseMethod("pay")
pay.employee <- function(x) x$salary / 12
m <- structure(list(name = "Ada", salary = 60000), class = c("manager", "employee"))
print(class(m))
print(pay(m))Output:
[1] "manager" "employee"
[1] 5000Writing the class vector by hand in every constructor repeats the parent's details. Instead the parent constructor takes a class argument and puts it in front of its own class, and the child constructor calls the parent one:
new_employee <- function(name, salary, ..., class = character()) {
structure(list(name = name, salary = salary, ...), class = c(class, "employee"))
}
new_manager <- function(name, salary, reports) {
new_employee(name, salary, reports = reports, class = "manager")
}
m <- new_manager("Ada", 60000, 4)
print(class(m))
print(names(m))Output:
[1] "manager" "employee"
[1] "name" "salary" "reports"The ... of the parent constructor collects the child's extra fields, here reports, and places them after the parent's own fields. A plain employee has no reports field at all:
new_employee <- function(name, salary, ..., class = character()) {
structure(list(name = name, salary = salary, ...), class = c(class, "employee"))
}
e <- new_employee("Bo", 40000)
print(class(e))
print(names(e))Output:
[1] "employee"
[1] "name" "salary"The order of the class vector matters: the most specific class comes first. With the parent first, its methods win and the child's methods are never used:
title <- function(x) UseMethod("title")
title.employee <- function(x) "employee"
title.manager <- function(x) "manager"
right <- structure(list(), class = c("manager", "employee"))
wrong <- structure(list(), class = c("employee", "manager"))
print(title(right))
print(title(wrong))Output:
[1] "manager"
[1] "employee"Challenge
EasyEmployees and managers are split over two files. Complete new_employee(name, salary, ..., class = character()) in Employee.R: it returns a list with name, salary and any extra fields from ..., with the class vector c(class, "employee"). Then complete new_manager(name, salary, reports) in Manager.R, which calls new_employee() with the extra field reports and the class manager.
label() and its employee method are given, so managers get a label without a method of their own. The supplied code reads lines employee Bo 40000 or manager Ada 60000 4 and prints the class vector, the field names and the label.
Your code goes in Employee.R and Manager.R. main.R holds the supplied input/output code and cannot be edited.
Try it yourself
source("Employee.R")
source("Manager.R")
# Supplied input/output code: keep it as it is
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
p <- strsplit(line, " ")[[1]]
x <- if (p[1] == "manager") new_manager(p[2], as.numeric(p[3]), as.numeric(p[4])) else new_employee(p[2], as.numeric(p[3]))
cat("class: ", paste(class(x), collapse = ", "), "\n", sep = "")
cat("fields: ", paste(names(x), collapse = ", "), "\n", sep = "")
cat(label(x), "\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 PayrollPractice on your own: Online R compiler