Extending With contains
Part of the Object Oriented Programming section of Coddy's R journey. Lesson 32 of 57.
contains = "Animal" makes a new S4 class a subclass of Animal. The subclass has every slot of its parent plus its own, and new() takes them all:
setClass("Animal", slots = c(name = "character", age = "numeric"))
setClass("Dog", contains = "Animal", slots = c(breed = "character"))
rex <- new("Dog", name = "Rex", age = 3, breed = "collie")
print(slotNames("Dog"))
cat(rex@name, rex@breed)Output:
[1] "breed" "name" "age"
Rex collieMethods written for the parent work for the child too. When a generic has no method for Dog, S4 uses the one for Animal:
setClass("Animal", slots = c(name = "character"))
setClass("Dog", contains = "Animal")
invisible(setGeneric("intro", function(a) standardGeneric("intro")))
setMethod("intro", "Animal", function(a) paste("I am", a@name))
print(intro(new("Dog", name = "Rex")))Output:
[1] "I am Rex"A child overrides a parent method by defining its own for the same generic. The most specific class wins, and other subclasses keep the parent's method:
setClass("Animal", slots = c(name = "character"))
setClass("Dog", contains = "Animal")
setClass("Cat", contains = "Animal")
invisible(setGeneric("sound", function(a) standardGeneric("sound")))
setMethod("sound", "Animal", function(a) "...")
setMethod("sound", "Dog", function(a) "woof")
cat(sound(new("Dog", name = "Rex")), sound(new("Cat", name = "Tom")))Output:
woof ...is(x, "Animal") is TRUE for a dog, and a slot declared as "Animal" accepts a Dog. Code written for the parent class works with every subclass:
setClass("Animal", slots = c(name = "character"))
setClass("Dog", contains = "Animal")
setClass("Owner", slots = c(pet = "Animal"))
rex <- new("Dog", name = "Rex")
o <- new("Owner", pet = rex)
cat(is(rex, "Animal"), is(o@pet, "Dog"))Output:
TRUE TRUEChallenge
EasyEmployees and managers are S4 classes in two files. Employee.R declares Employee (slots name, salary) and the generic describe(), and needs a method for Employee that returns Bo earns 40000. In Manager.R declare Manager, which contains Employee and adds the slot reports (numeric), and override describe() so it returns Ada earns 60000 and manages 4.
The supplied code reads lines employee Bo 40000 or manager Ada 60000 4 and prints describe(), whether the object is an employee, and its slots.
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", name = p[2], salary = as.numeric(p[3]), reports = as.numeric(p[4]))
} else {
new("Employee", name = p[2], salary = as.numeric(p[3]))
}
cat(describe(x), "\n", sep = "")
cat("is an employee: ", is(x, "Employee"), ", slots: ", paste(slotNames(x), 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 Meter7S4 Inheritance
Extending With containscallNextMethodVirtual ClassesChecking Types With is()Recap - Zoo Keeper2S3 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