Menu
Coddy logo textTech

Slots et accès

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

obj@slot <- value modifie un slot. Comme les objets S3, les objets S4 sont des valeurs : une fonction qui en modifie une agit sur sa propre copie et la renvoie :

setClass("Person", slots = c(name = "character", age = "numeric"))
birthday <- function(p) {
  p@age <- p@age + 1
  p
}
ada <- new("Person", name = "Ada", age = 36)
older <- birthday(ada)
cat(ada@age, older@age)

Sortie :

36 37

slot(obj, "name") fait la même chose que @ avec le nom du slot sous forme de chaîne, et fonctionne donc avec un nom stocké dans une variable. slotNames() liste les slots d’une classe ou d’un objet :

setClass("Person", slots = c(name = "character", age = "numeric"))
ada <- new("Person", name = "Ada", age = 36)
for (s in slotNames(ada)) cat(s, "=", format(slot(ada, s)), "\n")
slot(ada, "age") <- 37
print(ada@age)

Sortie :

name = Ada 
age = 36 
[1] 37

Chaque affectation est vérifiée par rapport au type déclaré, et pas seulement new(). Une valeur incorrecte est refusée et l’objet conserve son ancienne valeur :

setClass("Person", slots = c(name = "character", age = "numeric"))
ada <- new("Person", name = "Ada", age = 36)
ada@age <- "old"

Sortie :

Error in (function (cl, name, valueClass)  : 
  assignment of an object of class “character” is not valid for @‘age’ in an object of class “Person”; is(value, "numeric") is not TRUE
Execution halted

getSlots() renvoie chaque nom de slot avec son type déclaré, ce qui permet au code de convertir une entrée textuelle vers le type attendu par un slot :

setClass("Person", slots = c(name = "character", age = "numeric"))
types <- getSlots("Person")
print(types)
value <- "40"
if (types[["age"]] == "numeric") value <- as.numeric(value)
print(value + 1)

Sortie :

       name         age 
"character"   "numeric" 
[1] 41
challenge icon

Défi

Facile

La classe Profile dans Profile.R possède les slots name et city (caractère), ainsi que age (numérique). Complétez deux fonctions :

  • update_profile(p, field, value) s’arrête avec no field email (utilisez call. = FALSE) lorsque le champ n’est pas un slot ; sinon, elle convertit le texte value avec as.numeric() lorsque le slot est numérique, définit le slot avec slot() et renvoie le profil modifié.
  • profile_lines(p) renvoie une ligne par slot, dans l’ordre des slots : name: Ada.

Le code fourni lit un nom, puis des lignes comme city=Paris ou age=36, applique chacune d’elles et affiche les lignes du profil.

Votre code doit être placé dans Profile.R. main.R contient le code fourni pour les entrées et les sorties et ne peut pas être modifié.

Essayez vous-même

source("Profile.R")

# Code d'entrée/sortie fourni : le laisser tel quel
input <- suppressWarnings(readLines(file("stdin")))
p <- new("Profile", name = input[1], city = "unknown", age = 0)
for (line in input[-1]) {
  kv <- strsplit(line, "=")[[1]]
  p <- tryCatch(update_profile(p, kv[1], kv[2]), error = function(e) {
    cat("error: ", conditionMessage(e), "\n", sep = "")
    p
  })
}
for (l in profile_lines(p)) cat(l, "\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