Validateurs et fonctions utilitaires
Fait partie de la section Programmation orientée objet du Journey R de Coddy. Leçon 5 sur 57.
Le constructeur vérifie les types ; un validateur vérifie les valeurs. Par convention, validate_money() prend un objet, appelle stop() avec un message clair pour chaque règle qu’il enfreint, et renvoie l’objet lorsque tout va bien. call. = FALSE exclut l’appel de fonction du message :
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"))Sortie :
Error: amount must not be negative
Execution haltedLa fonction auxiliaire est la fonction appelée par les autres parties du code. Elle porte le nom de la classe, convertit ses entrées vers les types appropriés, applique les valeurs par défaut et transmet le résultat au constructeur puis au validateur :
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)Résultat :
12 USDLe code qui lit la saisie de l'utilisateur intercepte les erreurs du validateur avec tryCatch() et affiche conditionMessage(e), le texte passé à 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")
}Sortie :
ok 30
age must not be negative
age is too large Chacune des trois fonctions a une tâche. new_money() est stricte et rapide, pour le code qui possède déjà les bons types. validate_money() contient les règles concernant les valeurs, qui peuvent être nombreuses ou prendre du temps. money() est conviviale et c’est elle que le reste du programme utilise :
new_money() # types uniquement ; construit l'objet avec structure()
validate_money() # règles de valeur ; stop() avec un message, sinon return x
money() # convertit l'entrée, puis validate_money(new_money(...))Défi
Facilenew_score(points, max) dans Score.R construit un objet score. Complétez les autres fonctions dans le même fichier :
validate_score(x)s’arrête avecpoints must not be negative,max must be positiveoupoints must not exceed max, vérifiés dans cet ordre, et renvoie sinonx.score(points, max = 100)convertit les deux arguments avecas.double()et renvoievalidate_score(new_score(...)).format.score(x, ...)renvoie45/50 (90%), avec le pourcentage arrondi à l’entier le plus proche.
Utilisez call. = FALSE dans chaque appel à stop(). Le code fourni lit les lignes 45 50, affiche le score formaté, ou error: suivi du message.
Votre code doit être placé dans Score.R. main.R contient le code fourni pour les entrées et sorties et ne peut pas être modifié.
Essayez vous-même
source("Score.R")
# Code d'entrée/sortie fourni : le garder tel quel
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 = "")
}
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
1Bases de S3
Travailler avec les fichiersListes avec une classeFonctions constructricesMéthodes print et formatValidateurs et fonctions utilitairesRécapitulatif - Températures4Encapsulation dans R
Les fermetures comme objetsLes environnements comme objetsFonctions d’accèsProtéger l’étatRécapitulatif - Parcmètre2S3 : génériques et méthodes
Génériques et UseMethodMéthodes par défautMéthodes pour les génériques de baseNotions de base sur NextMethodRécapitulatif - Aires des formes5Classes S4
Définir des classes S4Slots et accèsVérifications de validitéMéthodes showRécapitulatif - Catalogue de produits8Classes de référence
Définition des classes de référenceMéthodes et mises à jour des champsSémantique de copieHéritage et callSuperRécapitulatif - File d’attente des tâches11Projet : gestion de bibliothèque
Livres et membresEmprunter des livres3Héritage S3
Vecteurs de classesOrdre de recherche des méthodesÉtendre avec NextMethodVérifier avec inherits()Récapitulatif - Paie du personnelEntraînez-vous par vous-même : Compilateur R en ligne