Menu
Coddy logo textTech

Classi virtuali

Fa parte della sezione Programmazione orientata agli oggetti del percorso R di Coddy. Lezione 34 di 57.

Una classe virtuale descrive ciò che una famiglia di classi ha in comune e non può avere oggetti propri. Dichiarala con representation("VIRTUAL"); le sue sottoclassi usano contains come di consueto:

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 

Un metodo per la classe virtuale funziona per ogni sottoclasse. Qui describe() per Shape chiama area(), che viene implementato da ogni sottoclasse, quindi la descrizione viene scritta una sola volta:

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 

Una classe virtuale può dichiarare degli slot, che ogni sottoclasse eredita:

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() crea una classe virtuale a partire da classi esistenti. Uno slot di quel tipo accetta una qualunque di esse, come un contatto che sia un indirizzo email oppure un numero di telefono:

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

Risultato:

character numeric 
refused 
challenge icon

Sfida

Facile

I pagamenti condividono la classe virtuale Payment (slot amount) e i generici fee() e receipt(), tutti in Payment.R. Completa:

  • in Payment.R, il metodo receipt() per Payment: card: 100.00 + 2.00 fee, costruito a partire dal nome della classe in minuscolo, da amount e da fee();
  • in Card.R, la classe Card (che contiene Payment) e il suo fee(): il 2% dell’importo;
  • in Cash.R, la classe Cash e il suo fee(): 0.

Il codice fornito legge righe card 100 o cash 20, stampa ogni ricevuta e il totale addebitato, quindi verifica che Payment sia virtuale e non possa essere creata.

Il tuo codice va in Payment.R, Card.R e Cash.R. main.R contiene il codice fornito per input/output e non può essere modificato.

Provalo tu

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 = "")
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore R online