Domknięcia jako obiekty
Część sekcji Programowanie obiektowe ścieżki R w Coddy. Lekcja 17 z 57.
W module Logic & Flow poznajesz domknięcia: funkcja utworzona wewnątrz innej funkcji zachowuje otaczające ją zmienne. Fabryka funkcji, która zwraca listę takich funkcji, tworzy obiekt. Jego zmienne lokalne to dane obiektu, a funkcje to jego metody:
make_account <- function(balance = 0) {
deposit <- function(x) balance <<- balance + x
get_balance <- function() balance
list(deposit = deposit, get_balance = get_balance)
}
acc <- make_account(100)
acc$deposit(50)
print(acc$get_balance())Wynik:
[1] 150Każde wywołanie fabryki ponownie uruchamia jej ciało, więc każdy obiekt ma własne zmienne. Zmiana jednego konta nie wpływa na drugie:
make_account <- function(balance = 0) {
list(deposit = function(x) balance <<- balance + x,
get_balance = function() balance)
}
ada <- make_account(100)
bo <- make_account(5)
ada$deposit(1)
cat(ada$get_balance(), bo$get_balance())Wynik:
101 5Dane są prywatne. balance nie jest elementem listy, więc acc$balance ma wartość NULL, a przypisanie do niego jedynie dodaje niezwiązany element. Funkcje na liście stanowią cały publiczny interfejs obiektu:
make_account <- function(balance = 0) {
list(get_balance = function() balance)
}
acc <- make_account(100)
print(acc$balance)
acc$balance <- 1e6
print(acc$get_balance())Wynik:
NULL
[1] 100Metody mogą wywoływać się nawzajem, gdy zostaną zdefiniowane jako funkcje lokalne przed utworzeniem listy. Tutaj add_many() ponownie używa add():
make_tally <- function() {
total <- 0
add <- function(x) total <<- total + x
add_many <- function(xs) for (x in xs) add(x)
get <- function() total
list(add = add, add_many = add_many, get = get)
}
t <- make_tally()
t$add(1)
t$add_many(c(2, 3, 4))
print(t$get())Wynik:
[1] 10Wyzwanie
ŁatwyUzupełnij funkcję fabrykującą make_counter(start = 0) w pliku Counter.R. Przechowuje ona bieżącą wartość prywatnie i zwraca listę z czterema funkcjami: increment() i decrement() zmieniają wartość o 1, reset() ustawia ją z powrotem na start, a value() ją zwraca.
Dostarczony kod odczytuje wartość początkową, a następnie polecenia +, - lub reset i wypisuje wartość po każdym z nich. Na końcu wypisuje nazwy elementów zwróconej listy, która musi zawierać wyłącznie te cztery funkcje.
Umieść swój kod w pliku Counter.R. Plik main.R zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.
Spróbuj swoich sił
source("Counter.R")
# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
input <- suppressWarnings(readLines(file("stdin")))
counter <- make_counter(as.numeric(input[1]))
for (cmd in input[-1]) {
if (cmd == "+") counter$increment()
if (cmd == "-") counter$decrement()
if (cmd == "reset") counter$reset()
cat(cmd, " -> ", counter$value(), "\n", sep = "")
}
cat("fields visible: ", paste(sort(names(counter)), collapse = ", "), "\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