Menu
Coddy logo textTech

Semantica della copia

Fa parte della sezione Programmazione orientata agli oggetti del percorso R di Coddy. Lezione 39 di 57.

Gli oggetti S3 e S4 sono valori: una funzione che ne modifica uno cambia la propria copia. Gli oggetti RC sono riferimenti: l'oggetto del chiamante cambia. La stessa funzione si comporta diversamente con i due tipi:

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)

Output:

1 2

$copy() crea un nuovo oggetto indipendente con gli stessi valori dei campi. Modificare la copia non altera l'originale:

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)

Output:

0 100

Una lista può contenere più volte lo stesso oggetto RC. Modificando un elemento, cambiano anche tutti gli altri. Crea un nuovo oggetto per ogni elemento quando devono essere indipendenti:

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)

Output:

5 0

identical(a, b) è TRUE per due nomi dello stesso oggetto RC, e FALSE per una copia, anche se i campi sono ancora uguali:

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)

Output:

TRUE FALSE TRUE
challenge icon

Sfida

Facile

Un editor di testo conserva dei punti di salvataggio. Dichiara la Reference Class Document in Document.R con il campo text (character) e un metodo type(s) che aggiunge s al testo. Poi scrivi checkpoint(doc), che restituisce una copia indipendente del documento.

La definizione con i metodi è racchiusa in suppressMessages(). Il codice fornito inizia con un punto di salvataggio, poi legge i comandi: save memorizza checkpoint(doc), undo ripristina una copia dell'ultimo punto di salvataggio e qualsiasi altra riga viene digitata. Dopo ogni comando stampa il testo e il testo salvato, quindi un punto di salvataggio non deve mai cambiare mentre si continua a digitare.

Il tuo codice va in Document.R. main.R contiene il codice di input/output fornito e non può essere modificato.

Provalo tu

source("Document.R")

# Codice di input/output fornito: lascialo così com'è
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 iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore R online