Menu
Coddy logo textTech

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 innerhalb einer anderen Funktion erstellte Funktion behält die Variablen um sie 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] 150

Jeder Aufruf der Factory führt ihren Rumpf erneut aus, sodass jedes Objekt seine eigenen Variablen erhält. Das Ändern eines Kontos wirkt sich nicht auf das andere aus:

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 5

Die Daten sind privat. balance ist kein Element der Liste, daher ist acc$balance NULL, und eine Zuweisung daran fügt lediglich ein unabhängiges 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] 100

Die Methoden können einander aufrufen, wenn sie als lokale Funktionen definiert werden, bevor die Liste erstellt wird. Hier verwendet add_many() add() erneut:

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] 10
challenge icon

Aufgabe

Einfach

Vervollständige die Factory 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 den Wert nach jedem Befehl 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 Eingabe-/Ausgabecode und darf nicht bearbeitet werden.

Probier es selbst

source("Counter.R")

# Bereitgestellter Ein-/Ausgabe-Code: belasse ihn wie er ist
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 = "")
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