Menu
Coddy logo textTech

Validatoren und Hilfsfunktionen

Teil des Abschnitts Objektorientierte Programmierung der R-Journey von Coddy. Lektion 5 von 57.

Der Konstruktor prüft Typen; ein Validator prüft Werte. Konventionell nimmt validate_money() ein Objekt entgegen, ruft für jede verletzte Regel stop() mit einer eindeutigen Meldung auf und gibt das Objekt zurück, wenn alles in Ordnung ist. call. = FALSE verhindert, dass der Funktionsaufruf in der Meldung erscheint:

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"))

Ausgabe:

Error: amount must not be negative
Execution halted

Der Hilfswrapper ist die Funktion, die von anderem Code aufgerufen wird. Sie ist nach der Klasse benannt, konvertiert ihre Eingabe in die richtigen Typen, ergänzt Standardwerte und leitet das Ergebnis durch den Konstruktor und den Validator:

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)

Ausgabe:

12 USD

Code, das Benutzereingaben liest, fängt die Fehler des Validators mit tryCatch() ab und zeigt conditionMessage(e) an, den an stop() übergebenen Text:

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")
}

Ausgabe:

ok 30 
age must not be negative 
age is too large 

Jede der drei Funktionen hat eine Aufgabe. new_money() ist streng und schnell und eignet sich für Code, der bereits die richtigen Typen hat. validate_money() enthält die Regeln für Werte, die langsam oder zahlreich sein können. money() ist benutzerfreundlich und wird vom restlichen Programm verwendet:

new_money()       # nur Typen; baut das Objekt mit structure()
validate_money()  # Wertregeln; stop() mit einer Nachricht, sonst return x
money()           # konvertiert die Eingabe, dann validate_money(new_money(...))
challenge icon

Aufgabe

Einfach

new_score(points, max) in Score.R erstellt ein score-Objekt. Vervollständige die anderen Funktionen in derselben Datei:

  • validate_score(x) bricht mit points must not be negative, max must be positive oder points must not exceed max ab, und zwar in dieser Reihenfolge geprüft, und gibt andernfalls x zurück.
  • score(points, max = 100) konvertiert beide Argumente mit as.double() und gibt validate_score(new_score(...)) zurück.
  • format.score(x, ...) gibt 45/50 (90%) zurück, wobei der Prozentsatz auf eine ganze Zahl gerundet wird.

Verwende in jedem stop() call. = FALSE. Der bereitgestellte Code liest Zeilen wie 45 50, gibt die formatierte Punktzahl oder error: und die Nachricht aus.

Dein Code gehört in Score.R. main.R enthält den bereitgestellten Eingabe-/Ausgabecode und darf nicht bearbeitet werden.

Probier es selbst

source("Score.R")

# Mitgelieferter Ein-/Ausgabe-Code: belasse ihn wie er ist
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 = "")
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-R-Compiler