Menu
Coddy logo textTech

Semântica de Cópia

Parte da seção Programação Orientada a Objetos do Journey de R da Coddy. Lição 39 de 57.

Objetos S3 e S4 são valores: uma função que altera um deles altera sua própria cópia. Objetos RC são referências: o objeto do chamador é alterado. A mesma função se comporta de maneira diferente para os dois 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)

Saída:

1 2

$copy() cria um novo objeto independente com os mesmos valores dos campos. Alterar a cópia não afeta o 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)

Saída:

0 100

Uma lista pode conter o mesmo objeto RC várias vezes. Alterar um elemento altera todos eles. Crie um novo objeto para cada elemento quando eles precisarem ser independentes:

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)

Saída:

5 0

identical(a, b) é TRUE para dois nomes do mesmo objeto RC e FALSE para uma cópia, mesmo enquanto os campos ainda são iguais:

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)

Saída:

TRUE FALSE TRUE
challenge icon

Desafio

Fácil

Um editor de texto mantém pontos de salvamento. Declare a classe de referência Document em Document.R com o campo text (caractere) e um método type(s) que acrescenta s ao texto. Em seguida, escreva checkpoint(doc), que retorna uma cópia independente do documento.

A definição com métodos é envolvida por suppressMessages(). O código fornecido começa com um ponto de salvamento e, em seguida, lê comandos: save armazena checkpoint(doc), undo volta para uma cópia do último ponto de salvamento e qualquer outra linha é digitada. Ele imprime o texto e o texto salvo após cada comando, portanto um ponto de salvamento nunca deve ser alterado quando a digitação continua.

Seu código deve ser colocado em Document.R. main.R contém o código fornecido de entrada/saída e não pode ser editado.

Experimente você mesmo

source("Document.R")

# Código de entrada/saída fornecido: mantenha-o como está
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 seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Compilador de R online