Menu
Coddy logo textTech

Dispatch su due argomenti

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

Un generico S4 può scegliere il proprio metodo in base alle classi di diversi argomenti. La firma elenca una classe per ogni argomento, quindi ogni coppia di classi può avere un proprio metodo:

setClass("Asteroid", slots = c(size = "numeric"))
setClass("Ship", slots = c(name = "character"))
invisible(setGeneric("collide", function(a, b) standardGeneric("collide")))
setMethod("collide", signature("Asteroid", "Ship"), function(a, b) paste(b@name, "is hit"))
setMethod("collide", signature("Ship", "Ship"), function(a, b) "two ships bump")
rock <- new("Asteroid", size = 3)
enterprise <- new("Ship", name = "Enterprise")
print(collide(rock, enterprise))
print(collide(enterprise, enterprise))

Output:

[1] "Enterprise is hit"
[1] "two ships bump"

La classe "ANY" corrisponde a ogni classe. Un metodo per signature("ANY", "ANY") è il ripiego che viene eseguito quando nessuna coppia più specifica è adatta:

setClass("Ship", slots = c(name = "character"))
invisible(setGeneric("collide", function(a, b) standardGeneric("collide")))
setMethod("collide", signature("Ship", "Ship"), function(a, b) "two ships bump")
setMethod("collide", signature("ANY", "ANY"), function(a, b) "nothing happens")
s <- new("Ship", name = "A")
cat(collide(s, s), "/", collide(s, 42), "/", collide("x", "y"))

Output:

two ships bump / nothing happens / nothing happens

L'ordine degli argomenti è importante: signature("A", "B") e signature("B", "A") sono metodi diversi. Anche classi di base come numeric e character possono comparire in una firma:

invisible(setGeneric("join", function(x, y) standardGeneric("join")))
setMethod("join", signature("character", "numeric"), function(x, y) paste(x, "number", y))
setMethod("join", signature("numeric", "character"), function(x, y) paste(y, "after number", x))
print(join("item", 3))
print(join(3, "item"))

Output:

[1] "item number 3"
[1] "item after number 3"

La classe "missing" in una firma corrisponde a un argomento che non è stato fornito affatto, quindi un generico può offrire una forma breve e una lunga:

invisible(setGeneric("greet", function(name, greeting) standardGeneric("greet")))
setMethod("greet", signature("character", "missing"), function(name, greeting) paste("Hello,", name))
setMethod("greet", signature("character", "character"), function(name, greeting) paste0(greeting, ", ", name))
print(greet("Ada"))
print(greet("Ada", "Good morning"))

Output:

[1] "Hello, Ada"
[1] "Good morning, Ada"
challenge icon

Sfida

Facile

I prezzi di spedizione dipendono dall'articolo e dalla zona. Le classi sono dichiarate in Item.R (Letter, Box, ciascuna con uno slot kg) e in Zone.R (Domestic, Abroad, ciascuna con uno slot name). In Rates.R crea la funzione generica shipping(item, zone) e un metodo per ogni coppia:

  • Letter a casa: 1; all'estero: 3.
  • Box a casa: 5 più 2 per kg; all'estero: 12 più 4 per kg.
  • Qualsiasi altra coppia: interrompi con no rate for this item and zone (usa call. = FALSE).

Il codice fornito legge righe box home 2.5 (articolo, zona, kg), dove le parole sconosciute restano testo semplice, e stampa box to home: 10.00 oppure error: e il messaggio.

Il tuo codice va in Item.R, Zone.R e Rates.R. main.R contiene il codice di input/output fornito e non può essere modificato.

Provalo tu

source("Item.R")
source("Zone.R")
source("Rates.R")

# Codice di input/output fornito: lascialo così com'è
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  p <- strsplit(line, " ")[[1]]
  kg <- as.numeric(p[3])
  item <- switch(p[1], letter = new("Letter", kg = kg), box = new("Box", kg = kg), kg)
  zone <- switch(p[2], home = new("Domestic", name = "home"), abroad = new("Abroad", name = "abroad"), p[2])
  out <- tryCatch(sprintf("%s to %s: %.2f", p[1], p[2], shipping(item, zone)),
                  error = function(e) paste("error:", conditionMessage(e)))
  cat(out, "\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