Menu
Coddy logo textTech

Comprobación con inherits()

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

inherits(x, "employee") pregunta si employee aparece en algún lugar del vector de clases de x, por lo que devuelve TRUE también para los gerentes. Comparar con class(x) == "employee" comprueba cada posición por separado y devuelve un vector, lo que falla en un if:

m <- structure(list(), class = c("manager", "employee"))
print(inherits(m, "employee"))
print(inherits(m, "intern"))
print(class(m) == "employee")

Salida:

[1] TRUE
[1] FALSE
[1] FALSE  TRUE

Dado varios nombres, inherits() es TRUE cuando el objeto tiene cualquiera de ellos. Con which = TRUE, devuelve, para cada nombre, su posición en el vector de clases, o 0 cuando falta:

p <- structure(list(), class = c("fragile", "express", "parcel"))
print(inherits(p, c("letter", "parcel")))
print(inherits(p, c("express", "letter", "parcel"), which = TRUE))

Salida:

[1] TRUE
[1] 2 0 3

Una función que solo tiene sentido para una familia de clases comprueba su argumento con inherits() y, de lo contrario, se detiene mostrando un mensaje claro:

raise <- function(x, pct) {
  if (!inherits(x, "employee")) stop("raise() needs an employee", call. = FALSE)
  x$salary <- x$salary * (1 + pct / 100)
  x
}
m <- structure(list(salary = 50000), class = c("manager", "employee"))
print(raise(m, 10)$salary)
print(tryCatch(raise(list(salary = 1), 10), error = function(e) conditionMessage(e)))

Salida:

[1] 55000
[1] "raise() needs an employee"

Filter() con inherits() selecciona los miembros de una familia de una lista mixta, incluidas todas las subclases:

staff <- list(
  structure(list(name = "Ada"), class = c("manager", "employee")),
  structure(list(name = "Bo"), class = "employee"),
  structure(list(name = "Cy"), class = c("intern", "employee")),
  structure(list(name = "Dee"), class = c("director", "manager", "employee"))
)
managers <- Filter(function(x) inherits(x, "manager"), staff)
print(vapply(managers, function(x) x$name, character(1)))

Salida:

[1] "Ada" "Dee"
challenge icon

Desafío

Fácil

Un catálogo contiene libros, ebooks y DVD. Los constructores se proporcionan en Item.R, Book.R, Ebook.R y Dvd.R; un ebook tiene la clase c("ebook", "book", "item"). En Catalogue.R, completa dos funciones con inherits():

  • count_of(items, kind) devuelve cuántos elementos tienen kind en cualquier posición de su vector de clases.
  • titles_of(items, kind) devuelve los títulos de esos elementos, en su orden.

El código proporcionado lee las líneas book Dune, ebook Emma, dvd Alien y las consultas ? book, e imprime book: 2 (Dune, Emma), o solo dvd: 0 cuando no hay coincidencias.

Tu código debe ir en Item.R, Book.R, Ebook.R, Dvd.R y Catalogue.R. main.R contiene el código de entrada/salida proporcionado y no se puede editar.

Pruébalo tú mismo

source("Item.R")
source("Book.R")
source("Ebook.R")
source("Dvd.R")
source("Catalogue.R")

# Código de entrada/salida suministrado: déjalo tal como está
input <- suppressWarnings(readLines(file("stdin")))
items <- list()
for (line in input) {
  p <- strsplit(line, " ")[[1]]
  rest <- paste(p[-1], collapse = " ")
  if (p[1] == "?") {
    titles <- titles_of(items, p[2])
    shown <- if (length(titles) > 0) paste0(" (", paste(titles, collapse = ", "), ")") else ""
    cat(p[2], ": ", count_of(items, p[2]), shown, "\n", sep = "")
  } else {
    items[[length(items) + 1]] <- switch(p[1], book = new_book(rest), ebook = new_ebook(rest), dvd = new_dvd(rest))
  }
}
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