Menu
Coddy logo textTech

Slots y acceso

Parte de la sección Programación orientada a objetos del Journey de R de Coddy. Lección 23 de 57.

obj@slot <- value cambia un slot. Al igual que los objetos S3, los objetos S4 son valores: una función que cambia uno opera sobre su propia copia y la devuelve:

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)

Salida:

36 37

slot(obj, "name") hace lo mismo que @ con el nombre del slot en una cadena, por lo que funciona con un nombre almacenado en una variable. slotNames() enumera los slots de una clase o un objeto:

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)

Salida:

name = Ada 
age = 36 
[1] 37

Cada asignación se comprueba con respecto al tipo declarado, no solo new(). Un valor incorrecto se rechaza y el objeto conserva el anterior:

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

Salida:

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() devuelve el nombre de cada ranura con su tipo declarado, lo que permite al código convertir la entrada de texto al tipo que espera una ranura:

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)

Salida:

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

Desafío

Fácil

La clase Profile en Profile.R tiene las ranuras name y city (carácter) y age (numérico). Completa dos funciones:

  • update_profile(p, field, value) se detiene con no field email (usa call. = FALSE) cuando el campo no es una ranura; de lo contrario, convierte el texto value con as.numeric() cuando la ranura es numérica, establece la ranura con slot() y devuelve el perfil modificado.
  • profile_lines(p) devuelve una línea por ranura, en el orden de las ranuras: name: Ada.

El código proporcionado lee un nombre, después líneas como city=Paris o age=36, aplica cada una e imprime las líneas del perfil.

Tu código va en Profile.R. main.R contiene el código de entrada/salida proporcionado y no se puede editar.

Pruébalo tú mismo

source("Profile.R")

# Código de entrada/salida suministrado: déjalo como está
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 iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación orientada a objetos

Practica por tu cuenta: Compilador de R online