Menu
Coddy logo textTech

Kopiersemantik

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

S3- und S4-Objekte sind Werte: Eine Funktion, die eines ändert, ändert ihre eigene Kopie. RC-Objekte sind Referenzen: Das Objekt des Aufrufers ändert sich. Dieselbe Funktion verhält sich bei den beiden Arten unterschiedlich:

setClass("S4Box", slots = c(n = "numeric"))
RCBox <- setRefClass("RCBox", fields = list(n = "numeric"))
bump_s4 <- function(b) { b@n <- b@n + 1; invisible(b) }
bump_rc <- function(b) b$n <- b$n + 1
v <- new("S4Box", n = 1)
r <- RCBox$new(n = 1)
bump_s4(v)
bump_rc(r)
cat(v@n, r$n)

Ausgabe:

1 2

$copy() erstellt ein neues, unabhängiges Objekt mit denselben Feldwerten. Wenn du die Kopie änderst, bleibt das Original unverändert:

Account <- setRefClass("Account", fields = list(balance = "numeric"))
a <- Account$new(balance = 100)
alias <- a
backup <- a$copy()
alias$balance <- 0
cat(a$balance, backup$balance)

Ausgabe:

0 100

Eine Liste kann dasselbe RC-Objekt mehrmals enthalten. Wenn ein Element geändert wird, ändern sich dadurch alle. Erstelle für jedes Element ein neues Objekt, wenn sie unabhängig voneinander sein müssen:

Counter <- setRefClass("Counter", fields = list(n = "numeric"))
one <- Counter$new(n = 0)
same <- list(one, one, one)
same[[1]]$n <- 5
fresh <- lapply(1:3, function(i) Counter$new(n = 0))
fresh[[1]]$n <- 5
cat(same[[3]]$n, fresh[[3]]$n)

Ausgabe:

5 0

identical(a, b) ist TRUE für zwei Namen desselben RC-Objekts und FALSE für eine Kopie, selbst wenn die Felder weiterhin gleich sind:

Account <- setRefClass("Account", fields = list(balance = "numeric"))
a <- Account$new(balance = 100)
b <- a
c2 <- a$copy()
cat(identical(a, b), identical(a, c2), c2$balance == a$balance)

Ausgabe:

TRUE FALSE TRUE
challenge icon

Aufgabe

Einfach

Ein Texteditor speichert Sicherungspunkte. Deklariere die Referenzklasse Document in Document.R mit dem Feld text (character) und einer Methode type(s), die s an den Text anhängt. Schreibe anschließend checkpoint(doc), das eine unabhängige Kopie des Dokuments zurückgibt.

Die Definition mit Methoden ist in suppressMessages() eingeschlossen. Der bereitgestellte Code beginnt mit einem Sicherungspunkt und liest anschließend Befehle: save speichert checkpoint(doc), undo kehrt zu einer Kopie des letzten Sicherungspunkts zurück, und jede andere Zeile wird eingegeben. Nach jedem Befehl gibt er den Text und den gespeicherten Text aus, daher darf sich ein Sicherungspunkt beim weiteren Eingeben niemals ändern.

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

Probier es selbst

source("Document.R")

# Gelieferter Input/Output-Code: belasse ihn wie er ist
input <- suppressWarnings(readLines(file("stdin")))
doc <- Document$new(text = "")
saved <- checkpoint(doc)
for (cmd in input) {
  if (cmd == "save") {
    saved <- checkpoint(doc)
  } else if (cmd == "undo") {
    doc <- checkpoint(saved)
  } else {
    doc$type(cmd)
  }
  cat(cmd, " -> [", doc$text, "] saved [", saved$text, "]\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