Menu
Coddy logo textTech

Vecteurs de classes

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

L’héritage de S3 provient du vecteur de classes. Un objet avec class = c("manager", "employee") est un manager et également un employé. Lorsqu’un générique n’a aucune méthode pour manager, la recherche de méthode se poursuit et utilise la méthode employee :

pay <- function(x) UseMethod("pay")
pay.employee <- function(x) x$salary / 12
m <- structure(list(name = "Ada", salary = 60000), class = c("manager", "employee"))
print(class(m))
print(pay(m))

Sortie :

[1] "manager"  "employee"
[1] 5000

Écrire le vecteur de classes à la main dans chaque constructeur répète les détails du parent. À la place, le constructeur parent prend un argument class et le place devant sa propre classe, tandis que le constructeur enfant appelle celui du parent :

new_employee <- function(name, salary, ..., class = character()) {
  structure(list(name = name, salary = salary, ...), class = c(class, "employee"))
}
new_manager <- function(name, salary, reports) {
  new_employee(name, salary, reports = reports, class = "manager")
}
m <- new_manager("Ada", 60000, 4)
print(class(m))
print(names(m))

Sortie :

[1] "manager"  "employee"
[1] "name"    "salary"  "reports"

Le ... du constructeur parent collecte les champs supplémentaires de l'enfant, ici reports, et les place après les propres champs du parent. Un employé ordinaire n'a pas du tout de champ reports :

new_employee <- function(name, salary, ..., class = character()) {
  structure(list(name = name, salary = salary, ...), class = c(class, "employee"))
}
e <- new_employee("Bo", 40000)
print(class(e))
print(names(e))

Sortie :

[1] "employee"
[1] "name"   "salary"

L’ordre du vecteur de classes est important : la classe la plus spécifique vient en premier. Lorsque la classe parente vient en premier, ses méthodes l’emportent et les méthodes de la classe enfant ne sont jamais utilisées :

title <- function(x) UseMethod("title")
title.employee <- function(x) "employee"
title.manager <- function(x) "manager"
right <- structure(list(), class = c("manager", "employee"))
wrong <- structure(list(), class = c("employee", "manager"))
print(title(right))
print(title(wrong))

Résultat :

[1] "manager"
[1] "employee"
challenge icon

Défi

Facile

Les employés et les managers sont répartis dans deux fichiers. Complète new_employee(name, salary, ..., class = character()) dans Employee.R : cette fonction renvoie une liste contenant name, salary et tous les champs supplémentaires de ..., avec le vecteur de classes c(class, "employee"). Complète ensuite new_manager(name, salary, reports) dans Manager.R ; cette fonction appelle new_employee() avec le champ supplémentaire reports et la classe manager.

label() et sa méthode employee sont fournies, afin que les managers obtiennent un libellé sans avoir leur propre méthode. Le code fourni lit des lignes telles que employee Bo 40000 ou manager Ada 60000 4, puis affiche le vecteur de classes, les noms des champs et le libellé.

Ton code doit se trouver dans Employee.R et Manager.R. main.R contient le code fourni pour les entrées et sorties et ne peut pas être modifié.

Essayez vous-même

source("Employee.R")
source("Manager.R")

# Code d'entrée/sortie fourni : le garder tel quel
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  p <- strsplit(line, " ")[[1]]
  x <- if (p[1] == "manager") new_manager(p[2], as.numeric(p[3]), as.numeric(p[4])) else new_employee(p[2], as.numeric(p[3]))
  cat("class: ", paste(class(x), collapse = ", "), "\n", sep = "")
  cat("fields: ", paste(names(x), collapse = ", "), "\n", sep = "")
  cat(label(x), "\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