Closures als Objekte
Teil des Abschnitts Objektorientierte Programmierung der R-Journey von Coddy. Lektion 17 von 57.
Du hast Closures in Logic & Flow kennengelernt: Eine Funktion, die innerhalb einer anderen Funktion erstellt wird, behält die Variablen um sich herum bei. Eine Funktionsfabrik, die eine Liste solcher Funktionen zurückgibt, erstellt ein Objekt. Ihre lokalen Variablen sind die Daten des Objekts, und die Funktionen sind seine Methoden:
make_account <- function(balance = 0) {
deposit <- function(x) balance <<- balance + x
get_balance <- function() balance
list(deposit = deposit, get_balance = get_balance)
}
acc <- make_account(100)
acc$deposit(50)
print(acc$get_balance())Ausgabe:
[1] 150Jeder Aufruf der Factory führt ihren Funktionskörper erneut aus, sodass jedes Objekt seine eigenen Variablen erhält. Wenn du ein Konto änderst, hat das keinen Einfluss auf das andere:
make_account <- function(balance = 0) {
list(deposit = function(x) balance <<- balance + x,
get_balance = function() balance)
}
ada <- make_account(100)
bo <- make_account(5)
ada$deposit(1)
cat(ada$get_balance(), bo$get_balance())Ausgabe:
101 5Die Daten sind privat. balance ist kein Element der Liste, daher ist acc$balance NULL, und eine Zuweisung daran fügt lediglich ein nicht zusammenhängendes Element hinzu. Die Funktionen in der Liste bilden die gesamte öffentliche Schnittstelle des Objekts:
make_account <- function(balance = 0) {
list(get_balance = function() balance)
}
acc <- make_account(100)
print(acc$balance)
acc$balance <- 1e6
print(acc$get_balance())Ausgabe:
NULL
[1] 100Die Methoden können sich gegenseitig aufrufen, wenn sie als lokale Funktionen definiert werden, bevor die Liste erstellt wird. Hier verwendet add_many() erneut add():
make_tally <- function() {
total <- 0
add <- function(x) total <<- total + x
add_many <- function(xs) for (x in xs) add(x)
get <- function() total
list(add = add, add_many = add_many, get = get)
}
t <- make_tally()
t$add(1)
t$add_many(c(2, 3, 4))
print(t$get())Ausgabe:
[1] 10Aufgabe
EinfachVervollständige die Fabrikfunktion make_counter(start = 0) in Counter.R. Sie hält den aktuellen Wert privat und gibt eine Liste mit vier Funktionen zurück: increment() und decrement() ändern den Wert um 1, reset() setzt ihn auf start zurück und value() gibt ihn zurück.
Der bereitgestellte Code liest den Startwert und anschließend die Befehle +, - oder reset ein und gibt nach jedem Befehl den Wert aus. Am Ende gibt er die Namen in der zurückgegebenen Liste aus. Diese darf nur die vier Funktionen enthalten.
Dein Code gehört in Counter.R. main.R enthält den bereitgestellten Ein-/Ausgabecode und darf nicht bearbeitet werden.
Probier es selbst
source("Counter.R")
# Vorgegebener Ein-/Ausgabecode: unverändert lassen
input <- suppressWarnings(readLines(file("stdin")))
counter <- make_counter(as.numeric(input[1]))
for (cmd in input[-1]) {
if (cmd == "+") counter$increment()
if (cmd == "-") counter$decrement()
if (cmd == "reset") counter$reset()
cat(cmd, " -> ", counter$value(), "\n", sep = "")
}
cat("fields visible: ", paste(sort(names(counter)), collapse = ", "), "\n", sep = "")
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1S3-Grundlagen
Arbeiten mit DateienListen mit einer KlasseKonstruktorfunktionenPrint- und Format-MethodenValidatoren und HilfsfunktionenRückblick – Temperaturen4Kapselung in R
Closures als ObjekteUmgebungen als ObjekteZugriffsfunktionenZustand schützenRückblick – Parkuhr2S3-Generics und Methoden
Generics und UseMethodStandardmethodenMethoden für Basis-GenericsGrundlagen von NextMethodWiederholung – Flächeninhalte von Formen5S4-Klassen
S4-Klassen definierenSlots und ZugriffGültigkeitsprüfungenShow-MethodenRückblick – Produktkatalog8Referenzklassen
Referenzklassen definierenMethoden und FeldänderungenKopiersemantikVererbung und callSuperZusammenfassung – Aufgabenwarteschlange11Projekt: Bibliotheksverwaltung
Bücher und MitgliederBücher ausleihenÜbe selbstständig: Online-R-Compiler