Menu
Coddy logo textTech

Semántica de copia

Parte de la sección Programación orientada a objetos del Journey de R de Coddy. Lección 39 de 57.

Los objetos S3 y S4 son valores: una función que cambia uno cambia su propia copia. Los objetos RC son referencias: el objeto de quien llama cambia. La misma función se comporta de manera diferente para los dos tipos:

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)

Salida:

1 2

$copy() crea un objeto nuevo e independiente con los mismos valores de campo. Cambiar la copia no afecta al original:

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)

Salida:

0 100

Una lista puede contener el mismo objeto RC varias veces. Cambiar un elemento cambia entonces todos ellos. Crea un objeto nuevo para cada elemento cuando deban ser independientes:

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)

Salida:

5 0

identical(a, b) es TRUE para dos nombres del mismo objeto RC, y FALSE para una copia, incluso cuando los campos siguen siendo iguales:

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)

Salida:

TRUE FALSE TRUE
challenge icon

Desafío

Fácil

Un editor de texto mantiene puntos de guardado. Declara la clase de referencia Document en Document.R con el campo text (carácter) y un método type(s) que añade s al texto. Después escribe checkpoint(doc), que devuelve una copia independiente del documento.

La definición con métodos está envuelta en suppressMessages(). El código proporcionado comienza con un punto de guardado y después lee comandos: save almacena checkpoint(doc), undo vuelve a una copia del último punto de guardado y cualquier otra línea se escribe. Imprime el texto y el texto guardado después de cada comando, por lo que un punto de guardado nunca debe cambiar cuando se continúa escribiendo.

Tu código va en Document.R. main.R contiene el código de entrada/salida proporcionado y no se puede editar.

Pruébalo tú mismo

source("Document.R")

# Código de entrada/salida suministrado: mantenlo tal cual
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 iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación orientada a objetos

Practica por tu cuenta: Compilador de R online