Menu
Coddy logo textTech

Chiusure come oggetti

Fa parte della sezione Programmazione orientata agli oggetti del percorso R di Coddy. Lezione 17 di 57.

Hai incontrato le closure in Logic & Flow: una funzione creata all'interno di un'altra funzione mantiene le variabili che la circondano. Una fabbrica di funzioni che restituisce un elenco di tali funzioni crea un oggetto. Le sue variabili locali sono i dati dell'oggetto e le funzioni sono i suoi metodi:

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())

Output:

[1] 150

Ogni chiamata alla funzione factory esegue di nuovo il proprio corpo, quindi ogni oggetto ha le proprie variabili. Modificare un conto non influisce sull’altro:

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())

Output:

101 5

I dati sono privati. balance non è un elemento della lista, quindi acc$balance è NULL e assegnargli un valore aggiunge solo un elemento non correlato. Le funzioni nella lista costituiscono l'intera interfaccia pubblica dell'oggetto:

make_account <- function(balance = 0) {
  list(get_balance = function() balance)
}
acc <- make_account(100)
print(acc$balance)
acc$balance <- 1e6
print(acc$get_balance())

Output:

NULL
[1] 100

I metodi possono richiamarsi a vicenda quando sono definiti come funzioni locali prima che venga creata la lista. Qui add_many() riutilizza 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())

Output:

[1] 10
challenge icon

Sfida

Facile

Completa la factory make_counter(start = 0) in Counter.R. Mantiene privato il valore corrente e restituisce una lista con quattro funzioni: increment() e decrement() modificano il valore di 1, reset() lo reimposta a start e value() lo restituisce.

Il codice fornito legge il valore iniziale, poi i comandi +, - o reset e stampa il valore dopo ciascuno. Alla fine stampa i nomi nella lista restituita, che deve contenere solo le quattro funzioni.

Il tuo codice va in Counter.R. main.R contiene il codice di input/output fornito e non può essere modificato.

Provalo tu

source("Counter.R")

# Supplied input/output code: keep it as it is
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 = "")
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore R online