Menu
Coddy logo textTech

Virtuelle Klassen

Teil des Abschnitts Objektorientierte Programmierung der R-Journey von Coddy. Lektion 34 von 57.

Eine virtuelle Klasse beschreibt, was eine Familie von Klassen gemeinsam hat, und kann keine eigenen Objekte haben. Deklariere sie mit representation("VIRTUAL"); ihre Unterklassen verwenden contains wie gewohnt:

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")

Ausgabe:

TRUE TRUE 
not allowed 

Eine Methode für die virtuelle Klasse funktioniert für jede Unterklasse. Hier ruft describe() für Shape area() auf, das jede Unterklasse implementiert, sodass die Beschreibung nur einmal geschrieben wird:

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")

Ausgabe:

Circle with area 3.14 
Square with area 4.00 

Eine virtuelle Klasse kann Slots deklarieren, die dann jede Unterklasse besitzt:

setClass("Shape", representation("VIRTUAL", label = "character"))
setClass("Square", contains = "Shape", slots = c(side = "numeric"))
sq <- new("Square", label = "tile", side = 2)
print(slotNames("Square"))

Ausgabe:

[1] "side"  "label"

setClassUnion() erstellt aus vorhandenen Klassen eine virtuelle Klasse. Ein Slot dieses Typs akzeptiert jede dieser Klassen, etwa einen Kontakt, der entweder eine E-Mail-Adresse oder eine Telefonnummer ist:

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")

Ausgabe:

character numeric 
refused 
challenge icon

Aufgabe

Einfach

Payments teilen die virtuelle Klasse Payment (Slot amount) und die Generics fee() und receipt(), alle in Payment.R. Vervollständige:

  • in Payment.R die receipt()-Methode für Payment: card: 100.00 + 2.00 fee, erstellt aus dem kleingeschriebenen Klassennamen, amount und fee();
  • in Card.R die Klasse Card (enthält Payment) und ihr fee(): 2 % des Betrags;
  • in Cash.R die Klasse Cash und ihr fee(): 0.

Der bereitgestellte Code liest Zeilen card 100 oder cash 20, gibt jede Quittung und den insgesamt berechneten Betrag aus und prüft anschließend, dass Payment virtuell ist und nicht erstellt werden kann.

Dein Code gehört in Payment.R, Card.R und Cash.R. main.R enthält den bereitgestellten Ein-/Ausgabecode und kann nicht bearbeitet werden.

Probier es selbst

source("Payment.R")
source("Card.R")
source("Cash.R")

# Bereitgestellter Ein-/Ausgabe-Code: belasse ihn wie er ist
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 = "")
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-R-Compiler