Menu
Coddy logo textTech

Extension avec contains

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

contains = "Animal" fait d’une nouvelle classe S4 une sous-classe de Animal. La sous-classe possède chaque slot de son parent ainsi que les siens, et new() les accepte tous :

setClass("Animal", slots = c(name = "character", age = "numeric"))
setClass("Dog", contains = "Animal", slots = c(breed = "character"))
rex <- new("Dog", name = "Rex", age = 3, breed = "collie")
print(slotNames("Dog"))
cat(rex@name, rex@breed)

Sortie :

[1] "breed" "name"  "age"  
Rex collie

Les méthodes écrites pour le parent fonctionnent également pour l’enfant. Lorsqu’un générique n’a aucune méthode pour Dog, S4 utilise celle de Animal :

setClass("Animal", slots = c(name = "character"))
setClass("Dog", contains = "Animal")
invisible(setGeneric("intro", function(a) standardGeneric("intro")))
setMethod("intro", "Animal", function(a) paste("I am", a@name))
print(intro(new("Dog", name = "Rex")))

Sortie :

[1] "I am Rex"

Un enfant surcharge une méthode parente en définissant la sienne pour le même générique. La classe la plus spécifique est prioritaire, et les autres sous-classes conservent la méthode de la classe parente :

setClass("Animal", slots = c(name = "character"))
setClass("Dog", contains = "Animal")
setClass("Cat", contains = "Animal")
invisible(setGeneric("sound", function(a) standardGeneric("sound")))
setMethod("sound", "Animal", function(a) "...")
setMethod("sound", "Dog", function(a) "woof")
cat(sound(new("Dog", name = "Rex")), sound(new("Cat", name = "Tom")))

Sortie :

woof ...

is(x, "Animal") est TRUE pour un chien, et un emplacement déclaré comme "Animal" accepte un Dog. Le code écrit pour la classe parente fonctionne avec chaque sous-classe :

setClass("Animal", slots = c(name = "character"))
setClass("Dog", contains = "Animal")
setClass("Owner", slots = c(pet = "Animal"))
rex <- new("Dog", name = "Rex")
o <- new("Owner", pet = rex)
cat(is(rex, "Animal"), is(o@pet, "Dog"))

Sortie :

TRUE TRUE
challenge icon

Défi

Facile

Les employés et les managers sont des classes S4 réparties dans deux fichiers. Employee.R déclare Employee (slots name, salary) ainsi que le générique describe(), et nécessite une méthode pour Employee qui renvoie Bo earns 40000. Dans Manager.R, déclarez Manager, qui contient Employee et ajoute le slot reports (numeric), puis redéfinissez describe() afin qu'il renvoie Ada earns 60000 and manages 4.

Le code fourni lit des lignes employee Bo 40000 ou manager Ada 60000 4 et affiche describe(), indique si l'objet est un employé, ainsi que ses slots.

Votre 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", name = p[2], salary = as.numeric(p[3]), reports = as.numeric(p[4]))
  } else {
    new("Employee", name = p[2], salary = as.numeric(p[3]))
  }
  cat(describe(x), "\n", sep = "")
  cat("is an employee: ", is(x, "Employee"), ", slots: ", paste(slotNames(x), collapse = ", "), "\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