Virtual Classes
Part of the Object Oriented Programming section of Coddy's R journey. Lesson 34 of 57.
A virtual class describes what a family of classes has in common, and cannot have objects of its own. Declare it with representation("VIRTUAL"); its subclasses use contains as usual:
setClass("Shape", representation("VIRTUAL"))
setClass("Circle", contains = "Shape", slots = c(r = "numeric"))
setClass("Square", contains = "Shape", slots = c(side = "numeric"))
cat(isVirtualClass("Shape"), is(new("Circle", r = 1), "Shape"), "\n")
cat(tryCatch({ new("Shape"); "made" }, error = function(e) "not allowed"), "\n")Output:
TRUE TRUE
not allowed A method for the virtual class works for every subclass. Here describe() for Shape calls area(), which each subclass implements, so the description is written once:
setClass("Shape", representation("VIRTUAL"))
setClass("Circle", contains = "Shape", slots = c(r = "numeric"))
setClass("Square", contains = "Shape", slots = c(side = "numeric"))
invisible(setGeneric("area", function(s) standardGeneric("area")))
invisible(setGeneric("describe", function(s) standardGeneric("describe")))
setMethod("area", "Circle", function(s) pi * s@r^2)
setMethod("area", "Square", function(s) s@side^2)
setMethod("describe", "Shape", function(s) sprintf("%s with area %.2f", class(s), area(s)))
for (s in list(new("Circle", r = 1), new("Square", side = 2))) cat(describe(s), "\n")Output:
Circle with area 3.14
Square with area 4.00 A virtual class can declare slots, which every subclass then has:
setClass("Shape", representation("VIRTUAL", label = "character"))
setClass("Square", contains = "Shape", slots = c(side = "numeric"))
sq <- new("Square", label = "tile", side = 2)
print(slotNames("Square"))Output:
[1] "side" "label"setClassUnion() makes a virtual class out of existing classes. A slot of that type accepts any of them, such as a contact that is either an email address or a phone number:
setClassUnion("Contact", c("character", "numeric"))
setClass("Friend", slots = c(name = "character", contact = "Contact"))
a <- new("Friend", name = "Ada", contact = "ada@x.org")
b <- new("Friend", name = "Bo", contact = 5550123)
cat(class(a@contact), class(b@contact), "\n")
cat(tryCatch({ new("Friend", name = "Cy", contact = TRUE); "ok" }, error = function(e) "refused"), "\n")Output:
character numeric
refused Challenge
EasyPayments share the virtual class Payment (slot amount) and the generics fee() and receipt(), all in Payment.R. Complete:
- in
Payment.R, thereceipt()method forPayment:card: 100.00 + 2.00 fee, built from the class name in lower case,amountandfee(); - in
Card.R, the classCard(containsPayment) and itsfee(): 2% of the amount; - in
Cash.R, the classCashand itsfee(): 0.
The supplied code reads lines card 100 or cash 20, prints each receipt and the total charged, then checks that Payment is virtual and cannot be created.
Your code goes in Payment.R, Card.R and Cash.R. main.R holds the supplied input/output code and cannot be edited.
Try it yourself
source("Payment.R")
source("Card.R")
source("Cash.R")
# Supplied input/output code: keep it as it is
input <- suppressWarnings(readLines(file("stdin")))
total <- 0
for (line in input) {
p <- strsplit(line, " ")[[1]]
amount <- as.numeric(p[2])
pay <- switch(p[1], card = new("Card", amount = amount), cash = new("Cash", amount = amount))
cat(receipt(pay), "\n", sep = "")
total <- total + amount + fee(pay)
}
cat(sprintf("charged: %.2f", total), "\n", sep = "")
cat("Payment is virtual: ", isVirtualClass("Payment"), "\n", sep = "")
cat(tryCatch({ new("Payment", amount = 1); "created a Payment" }, error = function(e) "cannot create a Payment"), "\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