R S4 Inheritance
S4 inheritance lets a new class build on a class that already exists. The new class keeps the parent slots and adds slots of its own.
A subclass adds a slot
Savings builds on Wallet with contains =. The new object fills two inherited slots and its own rate slot.
setClass("Wallet", slots = c(balance = "numeric", owner = "character"), prototype = list(balance = 0, owner = "Ana"))
setClass("Savings", contains = "Wallet", slots = c(rate = "numeric"), prototype = list(rate = 2))
s <- new("Savings", balance = 40, owner = "Bo", rate = 3)
print(s@balance)
print(s@owner)
print(s@rate)The full slot dump
print() shows the rate slot and both inherited slots. slotNames() lists all three names together.
setClass("Wallet", slots = c(balance = "numeric", owner = "character"), prototype = list(balance = 0, owner = "Ana"))
setClass("Savings", contains = "Wallet", slots = c(rate = "numeric"), prototype = list(rate = 2))
s <- new("Savings", balance = 40, owner = "Bo", rate = 3)
print(s)
print(slotNames(s))A parent method runs for a subclass
describe is written for Wallet. The same method runs for a Savings object and reads its inherited slots.
setClass("Wallet", slots = c(balance = "numeric", owner = "character"), prototype = list(balance = 0, owner = "Ana"))
setClass("Savings", contains = "Wallet", slots = c(rate = "numeric"), prototype = list(rate = 2))
g <- setGeneric("describe", function(x) standardGeneric("describe"))
setMethod("describe", "Wallet", function(x) cat(x@owner, "has", x@balance, "coins\n"))
s <- new("Savings", balance = 40, owner = "Bo", rate = 3)
describe(s)
w <- new("Wallet", balance = 7, owner = "Cy")
describe(w)is checks the parent class
is() reports TRUE for both the subclass and the parent class. A plain Wallet object is not a Savings object.
setClass("Wallet", slots = c(balance = "numeric", owner = "character"), prototype = list(balance = 0, owner = "Ana"))
setClass("Savings", contains = "Wallet", slots = c(rate = "numeric"), prototype = list(rate = 2))
s <- new("Savings", balance = 40, owner = "Bo", rate = 3)
print(is(s, "Savings"))
print(is(s, "Wallet"))
w <- new("Wallet", balance = 7, owner = "Cy")
print(is(w, "Savings"))Example
setClass("Wallet", slots = c(balance = "numeric", owner = "character"), prototype = list(balance = 0, owner = "Ana"))
setClass("Savings", contains = "Wallet", slots = c(rate = "numeric"), prototype = list(rate = 2))
g <- setGeneric("describe", function(x) standardGeneric("describe"))
setMethod("describe", "Wallet", function(x) cat(x@owner, "has", x@balance, "coins\n"))
s <- new("Savings", balance = 60, owner = "Ana", rate = 5)
print(is(s, "Wallet"))
describe(s)
print(s@rate)Key points
- contains = inside setClass() names the parent class.
- The subclass holds the parent slots alongside its own slots.
- new() fills the inherited slots and the new slots in one call.
- An object reads an inherited slot with @ in the same way as its own slot.
- is() returns TRUE when an object is checked against its parent class.
- A method written for the parent class also runs for the subclass.
In this example, Savings builds on Wallet and holds a balance of 60 with a rate of 5. is() confirms the object is also a Wallet, and the Wallet method describes it through its inherited slots.
Try it Yourself
Edit the code, then press Run.
Running is simulated ยท rdrr.io R Snippets
Exercise
What does contains = "Wallet" do inside a setClass() call for Savings?