Menu
Coddy logo textTech

Ordre de recherche des méthodes

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

À chaque appel, R parcourt le vecteur de classes de gauche à droite et exécute la première méthode qu’il trouve. Si aucune classe ne possède de méthode, il utilise la méthode par défaut. Différents objets d’une même hiérarchie peuvent s’arrêter à des niveaux différents :

move <- function(x) UseMethod("move")
move.animal <- function(x) "walks"
move.bird <- function(x) "flies"
move.default <- function(x) "stays"
penguin <- structure(list(), class = c("penguin", "bird", "animal"))
dog <- structure(list(), class = c("dog", "animal"))
rock <- structure(list(), class = "rock")
cat(move(penguin), move(dog), move(rock))

Résultat :

flies walks stays

Un enfant redéfinit une méthode parente en définissant la sienne. La redéfinition affecte uniquement l’enfant et tout ce qui se trouve en dessous de lui ; le parent et ses autres enfants conservent la méthode parente :

move <- function(x) UseMethod("move")
move.animal <- function(x) "walks"
move.bird <- function(x) "flies"
move.penguin <- function(x) "swims"
penguin <- structure(list(), class = c("penguin", "bird", "animal"))
sparrow <- structure(list(), class = c("bird", "animal"))
cat(move(penguin), move(sparrow))

Sortie :

swims flies

Chaque générique est recherché séparément. Un objet peut prendre sound() de sa propre classe et move() d'une classe parente, et une méthode parente peut appeler d'autres génériques qui effectuent à nouveau une répartition sur l'enfant :

sound <- function(x) UseMethod("sound")
move <- function(x) UseMethod("move")
describe <- function(x) UseMethod("describe")
sound.animal <- function(x) "..."
sound.dog <- function(x) "woof"
move.animal <- function(x) "walks"
describe.animal <- function(x) paste(x$name, "says", sound(x), "and", move(x))
rex <- structure(list(name = "Rex"), class = c("dog", "animal"))
print(describe(rex))

Résultat :

[1] "Rex says woof and walks"

Pour un objet doté d’un attribut de classe, la répartition examine uniquement cet attribut, puis la valeur par défaut. L’objet reste une liste en interne, mais une méthode pour list n’est pas essayée :

size <- function(x) UseMethod("size")
size.list <- function(x) "a list"
size.default <- function(x) "default"
bag <- structure(list(1, 2), class = "bag")
cat(size(list(1, 2)), "/", size(bag))

Sortie :

a list / default
challenge icon

Défi

Facile

Un carré est un rectangle dont les côtés sont de longueur égale. Dans Rectangle.R, écrivez les méthodes area.rectangle(), perimeter.rectangle() et name.rectangle(), qui renvoie rectangle 2x3. Dans Square.R, complétez new_square(side), qui appelle new_rectangle() avec la classe square, et redéfinissez uniquement name() avec name.square(), qui renvoie square 2. Les carrés doivent utiliser area() et perimeter() du rectangle.

Les génériques et new_rectangle() sont fournis. Le code fourni lit des lignes contenant deux nombres (un rectangle) ou un seul (un carré) et affiche square 2: area 4, perimeter 8.

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

Essayez vous-même

source("Rectangle.R")
source("Square.R")

# Code d'entrée/sortie fourni : le garder tel quel
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  n <- as.numeric(strsplit(line, " ")[[1]])
  s <- if (length(n) == 1) new_square(n[1]) else new_rectangle(n[1], n[2])
  cat(name(s), ": area ", area(s), ", perimeter ", 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