Menu
Coddy logo textTech

Extensión con NextMethod

Parte de la sección Programación orientada a objetos del Journey de R de Coddy. Lección 14 de 57.

Un método hijo suele hacer el trabajo del padre y algo más. NextMethod() llama al método padre, por lo que el hijo solo añade lo nuevo. El pago mensual de un gerente es el pago de un empleado más la bonificación:

pay <- function(x) UseMethod("pay")
pay.employee <- function(x) x$salary / 12
pay.manager <- function(x) NextMethod() + x$bonus / 12
m <- structure(list(salary = 60000, bonus = 12000), class = c("manager", "employee"))
e <- structure(list(salary = 36000), class = "employee")
cat(pay(e), pay(m))

Salida:

3000 6000

NextMethod() sigue funcionando a través de varios niveles. Cada método añade su parte y pasa el control a la clase posterior a la suya:

pay <- function(x) UseMethod("pay")
pay.employee <- function(x) x$salary / 12
pay.manager <- function(x) NextMethod() + x$bonus / 12
pay.director <- function(x) NextMethod() + 500
d <- structure(list(salary = 120000, bonus = 24000),
               class = c("director", "manager", "employee"))
print(pay(d))

Salida:

[1] 12500

Un método hijo también puede comprobar primero y delegar solo cuando la comprobación se supera. El método del padre devuelve el objeto modificado con su vector de clases completo, por lo que el resultado sigue siendo una cuenta de ahorros:

withdraw <- function(acc, amount) UseMethod("withdraw")
withdraw.account <- function(acc, amount) {
  if (amount > acc$balance) stop("insufficient funds", call. = FALSE)
  acc$balance <- acc$balance - amount
  acc
}
withdraw.savings <- function(acc, amount) {
  if (amount > 500) stop("savings limit is 500", call. = FALSE)
  NextMethod()
}
s <- structure(list(balance = 1000), class = c("savings", "account"))
s <- withdraw(s, 200)
cat(s$balance, class(s))

Salida:

800 savings account

Los constructores y los métodos reutilizan el elemento principal de la misma manera: new_manager() llama a new_employee(), y pay.manager() llama a NextMethod(). El código del empleado se escribe una vez y cada subclase se basa en él:

new_manager <- function(name, salary, bonus) {
  new_employee(name, salary, bonus = bonus, class = "manager")   # reutiliza el constructor
}
pay.manager <- function(x) NextMethod() + x$bonus / 12            # reutiliza el método
challenge icon

Desafío

Fácil

Las cuentas y las cuentas de ahorro están en dos archivos. En Account.R, completa withdraw.account(acc, amount), que se detiene con insufficient funds cuando el importe supera el saldo y, en caso contrario, devuelve la cuenta con el saldo reducido, y format.account(), que devuelve ada: 800. En Savings.R, completa withdraw.savings(), que se detiene con savings limit is 500 para importes superiores a 500 y, en caso contrario, continúa con NextMethod(), y format.savings(), que devuelve ada: 800 (savings) llamando a NextMethod().

Usa call. = FALSE. El genérico y los constructores ya están proporcionados. El código proporcionado lee savings ada 1000 o account bo 300, después los importes que se deben retirar; imprime withdrew 200 o refused: y el mensaje, y finalmente la cuenta formateada.

Tu código va en Account.R y Savings.R. main.R contiene el código proporcionado de entrada y salida y no se puede editar.

Pruébalo tú mismo

source("Account.R")
source("Savings.R")

# Código de entrada/salida suministrado: déjalo tal como está
input <- suppressWarnings(readLines(file("stdin")))
p <- strsplit(input[1], " ")[[1]]
acc <- if (p[1] == "savings") new_savings(p[2], as.numeric(p[3])) else new_account(p[2], as.numeric(p[3]))
for (amount in as.numeric(input[-1])) {
  acc <- tryCatch({
    acc <- withdraw(acc, amount)
    cat("withdrew ", amount, "\n", sep = "")
    acc
  }, error = function(e) {
    cat("refused: ", conditionMessage(e), "\n", sep = "")
    acc
  })
}
cat(format(acc), "\n", sep = "")
quiz iconPonte a prueba

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

Practica por tu cuenta: Compilador de R online