Menu
Coddy logo textTech

Estendere con NextMethod

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

Un metodo figlio spesso svolge il lavoro del metodo genitore più qualcosa in più. NextMethod() chiama il metodo genitore, quindi il metodo figlio aggiunge solo ciò che è nuovo. La retribuzione mensile di un manager è la retribuzione di un dipendente più il bonus:

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

Risultato:

3000 6000

NextMethod() continua a funzionare scendendo attraverso diversi livelli. Ogni metodo aggiunge la propria parte e passa la chiamata alla classe successiva:

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

Output:

[1] 12500

Un metodo figlio può anche effettuare prima un controllo e passare il controllo al metodo successivo solo se ha esito positivo. Il metodo del genitore restituisce l’oggetto modificato con il suo vettore di classi completo, quindi il risultato è ancora un conto di risparmio:

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

Output:

800 savings account

I costruttori e i metodi riutilizzano la classe genitore allo stesso modo: new_manager() chiama new_employee() e pay.manager() chiama NextMethod(). Il codice per i dipendenti viene scritto una sola volta e ogni sottoclasse si basa su di esso:

new_manager <- function(name, salary, bonus) {
  new_employee(name, salary, bonus = bonus, class = "manager")   # riutilizza il costruttore
}
pay.manager <- function(x) NextMethod() + x$bonus / 12            # riutilizza il metodo
challenge icon

Sfida

Facile

I conti e i conti di risparmio si trovano in due file. In Account.R completa withdraw.account(acc, amount), che si interrompe con insufficient funds quando l’importo supera il saldo e altrimenti restituisce il conto con il saldo ridotto, e format.account(), che restituisce ada: 800. In Savings.R completa withdraw.savings(), che si interrompe con savings limit is 500 per importi superiori a 500 e altrimenti prosegue con NextMethod(), e format.savings(), che restituisce ada: 800 (savings) chiamando NextMethod().

Usa call. = FALSE. La funzione generica e i costruttori sono forniti. Il codice fornito legge savings ada 1000 oppure account bo 300, poi gli importi da prelevare; stampa withdrew 200 oppure refused: e il messaggio, e infine il conto formattato.

Il tuo codice va inserito in Account.R e Savings.R. main.R contiene il codice fornito per l’input/output e non può essere modificato.

Provalo tu

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

# Codice di input/output fornito: lascialo così com'è
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 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