Cierres como objetos
Parte de la sección Programación orientada a objetos del Journey de R de Coddy. Lección 17 de 57.
Conociste las clausuras en Logic & Flow: una función creada dentro de otra función conserva las variables que la rodean. Una fábrica de funciones que devuelve una lista de esas funciones construye un objeto. Sus variables locales son los datos del objeto, y las funciones son sus métodos:
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())Salida:
[1] 150Cada llamada a la fábrica vuelve a ejecutar su cuerpo, por lo que cada objeto obtiene sus propias variables. Cambiar una cuenta no afecta a la otra:
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())Salida:
101 5Los datos son privados. balance no es un elemento de la lista, por lo que acc$balance es NULL y asignarle un valor solo añade un elemento no relacionado. Las funciones de la lista constituyen toda la interfaz pública del objeto:
make_account <- function(balance = 0) {
list(get_balance = function() balance)
}
acc <- make_account(100)
print(acc$balance)
acc$balance <- 1e6
print(acc$get_balance())Salida:
NULL
[1] 100Los métodos pueden llamarse entre sí cuando se definen como funciones locales antes de crear la lista. Aquí add_many() reutiliza 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())Salida:
[1] 10Desafío
FácilCompleta la fábrica make_counter(start = 0) en Counter.R. Mantiene privado el valor actual y devuelve una lista con cuatro funciones: increment() y decrement() cambian el valor en 1, reset() lo establece de nuevo en start y value() lo devuelve.
El código proporcionado lee el valor inicial, después los comandos +, - o reset, e imprime el valor después de cada uno. Al final imprime los nombres de la lista devuelta, que deben ser únicamente las cuatro funciones.
Tu código va en Counter.R. main.R contiene el código de entrada/salida proporcionado y no se puede editar.
Pruébalo tú mismo
source("Counter.R")
# Código de entrada/salida suministrado: déjalo tal como está
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 = "")
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación orientada a objetos
1Fundamentos de S3
Trabajar con archivosListas con una claseFunciones constructorasMétodos de impresión y formatoValidadores y auxiliaresRepaso: temperaturas4Encapsulación en R
Cierres como objetosEntornos como objetosFunciones de accesoProtección del estadoRepaso: parquímetro2S3 Genéricos y métodos
Genéricos y UseMethodMétodos predeterminadosMétodos para genéricos baseFundamentos de NextMethodRepaso: áreas de figuras5Clases S4
Definición de clases S4Slots y accesoComprobaciones de validezMétodos showRepaso - Catálogo de productos8Clases de referencia
Definición de clases de referenciaMétodos y actualizaciones de camposSemántica de copiaHerencia y callSuperRepaso: cola de tareas11Proyecto: Gestión de biblioteca
Libros y miembrosPréstamo de librosPractica por tu cuenta: Compilador de R online