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 100Lista 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 0identical(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 TRUEWyzwanie
ŁatwyEdytor 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 = "")
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy S3
Praca z plikamiListy z klasąFunkcje konstruktoraMetody print i formatWalidatory i funkcje pomocniczePowtórzenie — temperatury4Enkapsulacja w R
Domknięcia jako obiektyŚrodowiska jako obiektyFunkcje dostępoweOchrona stanuPodsumowanie – parkometr2Generics i metody S3
Generics i UseMethodMetody domyślneMetody dla podstawowych genericsPodstawy NextMethodPowtórzenie — pola figur5Klasy S4
Definiowanie klas S4Sloty i dostępSprawdzanie poprawnościMetody wyświetlaniaPodsumowanie – katalog produktów8Klasy referencyjne
Definiowanie klas referencyjnychMetody i aktualizacja pólSemantyka kopiowaniaDziedziczenie i callSuperPodsumowanie – kolejka zadań11Projekt: Zarządzanie biblioteką
Książki i czytelnicyWypożyczanie książek3Dziedziczenie S3
Wektory klasKolejność wyszukiwania metodRozszerzanie za pomocą NextMethodSprawdzanie za pomocą inherits()Powtórzenie — lista płac pracownikówPoćwicz samodzielnie: Kompilator R online