Despacho sobre dos argumentos
Parte de la sección Programación orientada a objetos del Journey de R de Coddy. Lección 29 de 57.
Un genérico S4 puede elegir su método según las clases de varios argumentos. La firma enumera una clase por argumento, por lo que cada par de clases puede tener su propio método:
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))Salida:
[1] "Enterprise is hit"
[1] "two ships bump"La clase "ANY" coincide con todas las clases. Un método para signature("ANY", "ANY") es la alternativa de reserva que se ejecuta cuando no encaja ningún par más específico:
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"))Salida:
two ships bump / nothing happens / nothing happensEl orden de los argumentos importa: signature("A", "B") y signature("B", "A") son métodos diferentes. Las clases básicas, como numeric y character, también pueden aparecer en 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"))Salida:
[1] "item number 3"
[1] "item after number 3"La clase "missing" en una signatura coincide con un argumento que no se proporcionó en absoluto, por lo que un genérico puede ofrecer una forma corta y una larga:
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"))Salida:
[1] "Hello, Ada"
[1] "Good morning, Ada"Desafío
FácilLos precios de envío dependen del artículo y de la zona. Las clases se declaran en Item.R (Letter, Box, cada una con un slot kg) y en Zone.R (Domestic, Abroad, cada una con un slot name). En Rates.R, crea el genérico shipping(item, zone) y un método por cada par:
Letteren casa: 1; en el extranjero: 3.Boxen casa: 5 más 2 por kg; en el extranjero: 12 más 4 por kg.- Cualquier otro par: detén la ejecución con
no rate for this item and zone(usacall. = FALSE).
El código proporcionado lee líneas box home 2.5 (artículo, zona, kg), donde las palabras desconocidas permanecen como texto sin formato, e imprime box to home: 10.00 o error: y el mensaje.
Tu código va en Item.R, Zone.R y Rates.R. main.R contiene el código proporcionado de entrada/salida y no se puede editar.
Pruébalo tú mismo
source("Item.R")
source("Zone.R")
source("Rates.R")
# Código de entrada/salida suministrado: déjalo tal como está
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 = "")
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación orientada a objetos
1Fundamentos de S3
Trabajar con archivosListas con una claseFunciones constructorasMétodos de impresión y formatoValidadores y auxiliaresRepaso: temperaturas4Encapsulación en R
Cierres como objetosEntornos como objetosFunciones de accesoProtección del estadoRepaso: parquímetro2S3 Genéricos y métodos
Genéricos y UseMethodMétodos predeterminadosMétodos para genéricos baseFundamentos de NextMethodRepaso: áreas de figuras5Clases S4
Definición de clases S4Slots y accesoComprobaciones de validezMétodos showRepaso - Catálogo de productos8Clases de referencia
Definición de clases de referenciaMétodos y actualizaciones de camposSemántica de copiaHerencia y callSuperRepaso: cola de tareas11Proyecto: Gestión de biblioteca
Libros y miembrosPréstamo de libros3Herencia en S3
Vectores de claseOrden de búsqueda de métodosExtensión con NextMethodComprobación con inherits()Repaso - Nómina del personal6S4 Genéricos y métodos
Creación de genéricosMétodos para funciones incorporadasDespacho sobre dos argumentossetValidity y validObjectRepaso: dinero y monedaPractica por tu cuenta: Compilador de R online