Menu
Coddy logo textTech

Erweitern mit NextMethod

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

Eine Methode eines untergeordneten Objekts erledigt oft die Arbeit des übergeordneten Objekts und noch ein wenig mehr. NextMethod() ruft die Methode des übergeordneten Objekts auf, sodass das untergeordnete Objekt nur das Neue hinzufügt. Das monatliche Gehalt eines Managers entspricht dem Gehalt eines Mitarbeiters zuzüglich des Bonus:

pay <- function(x) UseMethod("pay")
pay.employee <- function(x) x$salary / 12
pay.manager <- function(x) NextMethod() + x$bonus / 12
m <- structure(list(salary = 60000, bonus = 12000), class = c("manager", "employee"))
e <- structure(list(salary = 36000), class = "employee")
cat(pay(e), pay(m))

Ausgabe:

3000 6000

NextMethod() arbeitet über mehrere Ebenen hinweg weiter. Jede Methode fügt ihren Teil hinzu und gibt an die Klasse nach ihrer eigenen weiter:

pay <- function(x) UseMethod("pay")
pay.employee <- function(x) x$salary / 12
pay.manager <- function(x) NextMethod() + x$bonus / 12
pay.director <- function(x) NextMethod() + 500
d <- structure(list(salary = 120000, bonus = 24000),
               class = c("director", "manager", "employee"))
print(pay(d))

Ausgabe:

[1] 12500

Eine Kindmethode kann ebenfalls zuerst prüfen und die Verarbeitung nur dann weitergeben, wenn die Prüfung erfolgreich ist. Die Methode des Elternteils gibt das geänderte Objekt mit seinem vollständigen Klassenvektor zurück, daher ist das Ergebnis weiterhin ein Sparkonto:

withdraw <- function(acc, amount) UseMethod("withdraw")
withdraw.account <- function(acc, amount) {
  if (amount > acc$balance) stop("insufficient funds", call. = FALSE)
  acc$balance <- acc$balance - amount
  acc
}
withdraw.savings <- function(acc, amount) {
  if (amount > 500) stop("savings limit is 500", call. = FALSE)
  NextMethod()
}
s <- structure(list(balance = 1000), class = c("savings", "account"))
s <- withdraw(s, 200)
cat(s$balance, class(s))

Ausgabe:

800 savings account

Konstruktoren und Methoden verwenden das übergeordnete Element auf dieselbe Weise wieder: new_manager() ruft new_employee() auf, und pay.manager() ruft NextMethod() auf. Der Code für Mitarbeiter wird einmal geschrieben, und jede Unterklasse baut darauf auf:

new_manager <- function(name, salary, bonus) {
  new_employee(name, salary, bonus = bonus, class = "manager")   # den Konstruktor wiederverwenden
}
pay.manager <- function(x) NextMethod() + x$bonus / 12            # die Methode wiederverwenden
challenge icon

Aufgabe

Einfach

Konten und Sparkonten befinden sich in zwei Dateien. Vervollständige in Account.R withdraw.account(acc, amount), das bei einem Betrag über dem Kontostand mit insufficient funds abbricht und andernfalls das Konto mit dem niedrigeren Kontostand zurückgibt, sowie format.account(), das ada: 800 zurückgibt. Vervollständige in Savings.R withdraw.savings(), das bei Beträgen über 500 mit savings limit is 500 abbricht und andernfalls mit NextMethod() weiterleitet, sowie format.savings(), das durch Aufruf von NextMethod() ada: 800 (savings) zurückgibt.

Verwende call. = FALSE. Das Generikum und die Konstruktoren sind vorgegeben. Der bereitgestellte Code liest savings ada 1000 oder account bo 300 sowie anschließend die abzuhebenden Beträge ein; er gibt withdrew 200 oder refused: und die Meldung aus und formatiert schließlich das Konto.

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

Probier es selbst

source("Account.R")
source("Savings.R")

# Gelieferter Ein-/Ausgabecode: belasse ihn wie er ist
input <- suppressWarnings(readLines(file("stdin")))
p <- strsplit(input[1], " ")[[1]]
acc <- if (p[1] == "savings") new_savings(p[2], as.numeric(p[3])) else new_account(p[2], as.numeric(p[3]))
for (amount in as.numeric(input[-1])) {
  acc <- tryCatch({
    acc <- withdraw(acc, amount)
    cat("withdrew ", amount, "\n", sep = "")
    acc
  }, error = function(e) {
    cat("refused: ", conditionMessage(e), "\n", sep = "")
    acc
  })
}
cat(format(acc), "\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