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 happensL'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"Sfida
FacileI 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:
Lettera casa: 1; all'estero: 3.Boxa 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(usacall. = 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 = "")
}
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
1Nozioni di base su S3
Lavorare con i fileListe con una classeFunzioni costruttriciMetodi di stampa e formattazioneValidatori e funzioni di supportoRipasso - Temperature4Incapsulamento in R
Chiusure come oggettiAmbienti come oggettiFunzioni di accessoProteggere lo statoRiepilogo - Parcometro2Generics e metodi S3
Generics e UseMethodMetodi predefinitiMetodi per i generics di baseNozioni di base su NextMethodRiepilogo - Aree delle forme5Classi S4
Definire le classi S4Slot e accessoControlli di validitàMetodi showRiepilogo - Catalogo prodotti8Classi di riferimento
Definizione delle classi di riferimentoMetodi e aggiornamenti dei campiSemantica della copiaEreditarietà e callSuperRiepilogo - coda di attività11Progetto: Gestione della biblioteca
Libri e iscrittiPrestito dei libri3Ereditarietà S3
Vettori di classeOrdine di ricerca dei metodiEstendere con NextMethodVerificare con inherits()Riepilogo - Retribuzioni del personale6Generici e metodi S4
Creare genericiMetodi per gli elementi integratiDispatch su due argomentisetValidity e validObjectRiepilogo - Denaro e valutaEsercitati da solo: Compilatore R online