Menu
Coddy logo textTech

Création de génériques

Fait partie de la section Programmation orientée objet du Journey R de Coddy. Leçon 27 sur 57.

Un générique S4 est créé avec setGeneric(). Son corps de fonction est standardGeneric("name"), l’équivalent S4 de UseMethod(). setGeneric() renvoie le nom du générique, qui est affiché lorsqu’il est appelé au niveau supérieur :

setGeneric("area", function(shape) standardGeneric("area"))

Résultat :

[1] "area"

Enveloppez l’appel dans invisible() pour exclure cette ligne de la sortie. setMethod("area", "Circle", ...) ajoute ensuite la méthode pour une classe :

setClass("Circle", slots = c(r = "numeric"))
setClass("Square", slots = c(side = "numeric"))
invisible(setGeneric("area", function(shape) standardGeneric("area")))
setMethod("area", "Circle", function(shape) pi * shape@r^2)
setMethod("area", "Square", function(shape) shape@side^2)
cat(area(new("Circle", r = 1)), area(new("Square", side = 3)))

Sortie :

3.141593 9

Une méthode possède les mêmes arguments que son générique. Lorsque le générique contient ..., une méthode peut ajouter ses propres arguments nommés après ceux-ci :

setClass("Circle", slots = c(r = "numeric"))
invisible(setGeneric("describe", function(x, ...) standardGeneric("describe")))
setMethod("describe", "Circle", function(x, ..., digits = 2) {
  paste("circle of area", round(pi * x@r^2, digits))
})
c1 <- new("Circle", r = 2)
print(describe(c1))
print(describe(c1, digits = 4))

Résultat :

[1] "circle of area 12.57"
[1] "circle of area 12.5664"

setMethod() nécessite que le générique existe déjà, le fichier contenant setGeneric() est donc chargé en premier. Un appel pour une classe sans méthode s'arrête avec une erreur qui indique la signature :

invisible(setGeneric("area", function(shape) standardGeneric("area")))
setClass("Circle", slots = c(r = "numeric"))
setMethod("area", "Circle", function(shape) pi * shape@r^2)
area(42)

Sortie :

Error: unable to find an inherited method for function ‘area’ for signature ‘shape = "numeric"’
Execution halted
challenge icon

Défi

Facile

Les formes sont des classes S4 réparties dans trois fichiers. Dans Shape.R, créez les génériques area(shape) et perimeter(shape) avec setGeneric(), enveloppés dans invisible(). Dans Circle.R et Square.R, les classes sont déclarées ; ajoutez les méthodes area et perimeter de chacune avec setMethod().

Le code fourni lit les lignes circle 2 ou square 3 et affiche circle: area 12.57, perimeter 12.57.

Votre code doit être placé dans Shape.R, Circle.R et Square.R. main.R contient le code d’entrée/sortie fourni et ne peut pas être modifié.

Essayez vous-même

source("Shape.R")
source("Circle.R")
source("Square.R")

# Code d'entrée/sortie fourni : le garder tel quel
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  p <- strsplit(line, " ")[[1]]
  s <- if (p[1] == "circle") new("Circle", r = as.numeric(p[2])) else new("Square", side = as.numeric(p[2]))
  cat(sprintf("%s: area %.2f, perimeter %.2f", p[1], area(s), perimeter(s)), "\n", sep = "")
}
quiz iconTestez-vous

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

Entraînez-vous par vous-même : Compilateur R en ligne