Menu
Coddy logo textTech

Slots e acesso

Parte da seção Programação Orientada a Objetos do Journey de R da Coddy. Lição 23 de 57.

obj@slot <- value altera um slot. Assim como os objetos S3, os objetos S4 são valores: uma função que altera um deles opera em sua própria cópia e a retorna:

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)

Saída:

36 37

slot(obj, "name") faz o mesmo que @ com o nome do slot em uma string, portanto funciona com um nome armazenado em uma variável. slotNames() lista os slots de uma classe ou 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)

Saída:

name = Ada 
age = 36 
[1] 37

Cada atribuição é verificada em relação ao tipo declarado, não apenas new(). Um valor incorreto é recusado, e o objeto mantém o valor antigo:

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

Saída:

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() retorna o nome de cada slot com seu tipo declarado, o que permite ao código converter a entrada de texto para o tipo esperado por um 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)

Saída:

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

Desafio

Fácil

A classe Profile em Profile.R tem os slots name e city (character) e age (numeric). Complete duas funções:

  • update_profile(p, field, value) interrompe com no field email (use call. = FALSE) quando o campo não é um slot; caso contrário, converte o texto value com as.numeric() quando o slot é numeric, define o slot com slot() e retorna o perfil alterado.
  • profile_lines(p) retorna uma linha por slot, na ordem dos slots: name: Ada.

O código fornecido lê um nome, depois linhas como city=Paris ou age=36, aplica cada uma delas e imprime as linhas do perfil.

Seu código deve ficar em Profile.R. main.R contém o código fornecido de entrada/saída e não pode ser editado.

Experimente você mesmo

source("Profile.R")

# Código de entrada/saída fornecido: mantenha-o 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 iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Compilador de R online