Dispatch sur deux arguments
Fait partie de la section Programmation orientée objet du Journey R de Coddy. Leçon 29 sur 57.
Un générique S4 peut choisir sa méthode en fonction des classes de plusieurs arguments. La signature répertorie une classe par argument, de sorte que chaque paire de classes puisse avoir sa propre méthode :
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))Résultat :
[1] "Enterprise is hit"
[1] "two ships bump"La classe "ANY" correspond à chaque classe. Une méthode pour signature("ANY", "ANY") est la solution de repli qui s’exécute lorsqu’aucune paire plus spécifique ne correspond :
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"))Sortie :
two ships bump / nothing happens / nothing happensL’ordre des arguments est important : signature("A", "B") et signature("B", "A") sont des méthodes différentes. Des classes de base telles que numeric et character peuvent également apparaître dans une signature :
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"))Sortie :
[1] "item number 3"
[1] "item after number 3"La classe "missing" dans une signature correspond à un argument qui n’a pas du tout été fourni, de sorte qu’un générique peut proposer une forme courte et une forme longue :
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"))Sortie :
[1] "Hello, Ada"
[1] "Good morning, Ada"Défi
FacileLes tarifs d’expédition dépendent de l’article et de la zone. Les classes sont déclarées dans Item.R (Letter, Box, chacune avec un slot kg) et Zone.R (Domestic, Abroad, chacune avec un slot name). Dans Rates.R, créez le générique shipping(item, zone) et une méthode pour chaque paire :
Letterà domicile : 1 ; à l’étranger : 3.Boxà domicile : 5 plus 2 par kg ; à l’étranger : 12 plus 4 par kg.- Toute autre paire : arrêtez l’exécution avec
no rate for this item and zone(utilisezcall. = FALSE).
Le code fourni lit des lignes box home 2.5 (article, zone, kg), où les mots inconnus restent du texte simple, et affiche box to home: 10.00 ou error: suivi du message.
Votre code va dans Item.R, Zone.R et Rates.R. main.R contient le code fourni d’entrée/sortie et ne peut pas être modifié.
Essayez vous-même
source("Item.R")
source("Zone.R")
source("Rates.R")
# Code d'entrée/sortie fourni : le garder tel quel
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 = "")
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation orientée objet
1Bases de S3
Travailler avec les fichiersListes avec une classeFonctions constructricesMéthodes print et formatValidateurs et fonctions utilitairesRécapitulatif - Températures4Encapsulation dans R
Les fermetures comme objetsLes environnements comme objetsFonctions d’accèsProtéger l’étatRécapitulatif - Parcmètre2S3 : génériques et méthodes
Génériques et UseMethodMéthodes par défautMéthodes pour les génériques de baseNotions de base sur NextMethodRécapitulatif - Aires des formes5Classes S4
Définir des classes S4Slots et accèsVérifications de validitéMéthodes showRécapitulatif - Catalogue de produits8Classes de référence
Définition des classes de référenceMéthodes et mises à jour des champsSémantique de copieHéritage et callSuperRécapitulatif - File d’attente des tâches11Projet : gestion de bibliothèque
Livres et membresEmprunter des livres3Héritage S3
Vecteurs de classesOrdre de recherche des méthodesÉtendre avec NextMethodVérifier avec inherits()Récapitulatif - Paie du personnel6S4 Génériques et méthodes
Création de génériquesMéthodes pour les fonctions intégréesDispatch sur deux argumentssetValidity et validObjectRécapitulatif - Argent et deviseEntraînez-vous par vous-même : Compilateur R en ligne