Validadores y auxiliares
Parte de la sección Programación orientada a objetos del Journey de R de Coddy. Lección 5 de 57.
El constructor comprueba los tipos; un validador comprueba los valores. Por convención, validate_money() toma un objeto, llama a stop() con un mensaje claro por cada regla que infringe y devuelve el objeto cuando todo está bien. call. = FALSE mantiene la llamada a la función fuera del mensaje:
new_money <- function(amount = double(), currency = character()) {
stopifnot(is.double(amount), is.character(currency))
structure(list(amount = amount, currency = currency), class = "money")
}
validate_money <- function(x) {
if (x$amount < 0) stop("amount must not be negative", call. = FALSE)
if (nchar(x$currency) != 3) stop("currency must have 3 letters", call. = FALSE)
x
}
m <- validate_money(new_money(-5, "EUR"))Salida:
Error: amount must not be negative
Execution haltedEl helper es la función a la que llama otro código. Recibe su nombre de la clase, convierte su entrada a los tipos correctos, completa los valores no predeterminados y pasa el resultado por el constructor y el validador:
new_money <- function(amount = double(), currency = character()) {
stopifnot(is.double(amount), is.character(currency))
structure(list(amount = amount, currency = currency), class = "money")
}
validate_money <- function(x) {
if (x$amount < 0) stop("amount must not be negative", call. = FALSE)
x
}
money <- function(amount, currency = "EUR") {
validate_money(new_money(as.double(amount), toupper(currency)))
}
m <- money("12", "usd")
cat(m$amount, m$currency)Salida:
12 USDEl código que lee la entrada del usuario captura los errores del validador con tryCatch() y muestra conditionMessage(e), el texto pasado a stop():
validate_age <- function(x) {
if (x$years < 0) stop("age must not be negative", call. = FALSE)
if (x$years > 150) stop("age is too large", call. = FALSE)
x
}
age <- function(years) validate_age(structure(list(years = as.double(years)), class = "age"))
for (input in c("30", "-2", "200")) {
result <- tryCatch(paste("ok", age(input)$years), error = function(e) conditionMessage(e))
cat(result, "\n")
}Salida:
ok 30
age must not be negative
age is too large Cada una de las tres funciones tiene una tarea. new_money() es estricta y rápida, para código que ya tiene los tipos correctos. validate_money() contiene las reglas sobre los valores, que pueden ser numerosas o tardar en procesarse. money() es sencilla de usar y es la que utiliza el resto del programa:
new_money() # solo tipos; construye el objeto con structure()
validate_money() # reglas de valor; stop() con un mensaje, si no devuelve x
money() # convierte la entrada, luego validate_money(new_money(...))Desafío
Fácilnew_score(points, max) en Score.R construye un objeto score. Completa las otras funciones del mismo archivo:
validate_score(x)se detiene conpoints must not be negative,max must be positiveopoints must not exceed max, comprobados en ese orden, y de lo contrario devuelvex.score(points, max = 100)convierte ambos argumentos conas.double()y devuelvevalidate_score(new_score(...)).format.score(x, ...)devuelve45/50 (90%), con el porcentaje redondeado a un número entero.
Usa call. = FALSE en cada stop(). El código proporcionado lee las líneas 45 50, imprime la puntuación formateada o error: y el mensaje.
Tu código va en Score.R. main.R contiene el código proporcionado de entrada/salida y no se puede editar.
Pruébalo tú mismo
source("Score.R")
# Código de entrada/salida suministrado: déjalo tal como está
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
p <- strsplit(line, " ")[[1]]
s <- tryCatch(score(p[1], p[2]), error = function(e) conditionMessage(e))
if (is.character(s)) cat("error: ", s, "\n", sep = "") else cat(format(s), "\n", sep = "")
}
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
1Fundamentos de S3
Trabajar con archivosListas con una claseFunciones constructorasMétodos de impresión y formatoValidadores y auxiliaresRepaso: temperaturas4Encapsulación en R
Cierres como objetosEntornos como objetosFunciones de accesoProtección del estadoRepaso: parquímetro2S3 Genéricos y métodos
Genéricos y UseMethodMétodos predeterminadosMétodos para genéricos baseFundamentos de NextMethodRepaso: áreas de figuras5Clases S4
Definición de clases S4Slots y accesoComprobaciones de validezMétodos showRepaso - Catálogo de productos8Clases de referencia
Definición de clases de referenciaMétodos y actualizaciones de camposSemántica de copiaHerencia y callSuperRepaso: cola de tareas11Proyecto: Gestión de biblioteca
Libros y miembrosPréstamo de librosPractica por tu cuenta: Compilador de R online