Menu
Coddy logo textTech

Semantyka kopiowania

Część sekcji Programowanie obiektowe ścieżki R w Coddy. Lekcja 39 z 57.

Obiekty S3 i S4 są wartościami: funkcja, która zmienia jeden z nich, zmienia jego własną kopię. Obiekty RC są referencjami: obiekt wywołującego ulega zmianie. Ta sama funkcja zachowuje się inaczej dla tych dwóch rodzajów:

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)

Wynik:

1 2

$copy() tworzy nowy, niezależny obiekt z takimi samymi wartościami pól. Zmiana kopii nie wpływa na oryginał:

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)

Wynik:

0 100

Lista może kilka razy zawierać ten sam obiekt RC. Zmiana jednego elementu zmienia wtedy je wszystkie. Jeśli mają być niezależne, utwórz nowy obiekt dla każdego elementu:

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)

Wynik:

5 0

identical(a, b) zwraca TRUE dla dwóch nazw tego samego obiektu RC, a FALSE dla kopii, nawet jeśli pola są nadal równe:

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)

Wynik:

TRUE FALSE TRUE
challenge icon

Wyzwanie

Łatwy

Edytor tekstu przechowuje punkty zapisu. Zadeklaruj klasę Reference Class Document w pliku Document.R z polem text (character) oraz metodą type(s), która dopisuje s do tekstu. Następnie napisz checkpoint(doc), która zwraca niezależną kopię dokumentu.

Definicja z metodami jest opakowana w suppressMessages(). Dostarczony kod rozpoczyna od punktu zapisu, a następnie odczytuje polecenia: save zapisuje checkpoint(doc), undo przywraca kopię ostatniego punktu zapisu, a każdy inny wiersz jest wpisywany. Po każdym poleceniu kod wypisuje tekst i zapisany tekst, dlatego punkt zapisu nigdy nie może się zmienić podczas dalszego wpisywania.

Twój kod umieść w pliku Document.R. Plik main.R zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.

Spróbuj swoich sił

source("Document.R")

# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
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 iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator R online