Rozszerzanie za pomocą NextMethod
Część sekcji Programowanie obiektowe ścieżki R w Coddy. Lekcja 14 z 57.
Metoda klasy potomnej często wykonuje pracę metody klasy nadrzędnej i dodaje do niej coś jeszcze. NextMethod() wywołuje metodę klasy nadrzędnej, więc klasa potomna dodaje tylko to, co nowe. Miesięczne wynagrodzenie menedżera to wynagrodzenie pracownika powiększone o premię:
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))Wynik:
3000 6000NextMethod() działa dalej przez kilka poziomów. Każda metoda dodaje swoją część i przekazuje działanie klasie następującej po niej:
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))Wynik:
[1] 12500Metoda potomna może również najpierw przeprowadzić kontrolę i przekazać obsługę dalej tylko wtedy, gdy kontrola się powiedzie. Metoda klasy nadrzędnej zwraca zmieniony obiekt z pełnym wektorem klas, więc wynik nadal jest kontem oszczędnościowym:
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))Wynik:
800 savings accountKonstruktory i metody ponownie wykorzystują klasę nadrzędną w ten sam sposób: new_manager() wywołuje new_employee(), a pay.manager() wywołuje NextMethod(). Kod pracownika zapisuje się raz, a każda podklasa go rozszerza:
new_manager <- function(name, salary, bonus) {
new_employee(name, salary, bonus = bonus, class = "manager") # wykorzystaj ponownie konstruktor
}
pay.manager <- function(x) NextMethod() + x$bonus / 12 # wykorzystaj ponownie metodęWyzwanie
ŁatwyKonta i konta oszczędnościowe znajdują się w dwóch plikach. W Account.R uzupełnij withdraw.account(acc, amount), która przerywa działanie z komunikatem insufficient funds, gdy kwota przekracza saldo, a w przeciwnym razie zwraca konto z niższym saldem, oraz format.account(), która zwraca ada: 800. W Savings.R uzupełnij withdraw.savings(), która przerywa działanie z komunikatem savings limit is 500 dla kwot powyżej 500, a w przeciwnym razie przekazuje sterowanie dalej za pomocą NextMethod(), oraz format.savings(), która zwraca ada: 800 (savings), wywołując NextMethod().
Użyj call. = FALSE. Funkcja generyczna i konstruktory są już podane. Dostarczony kod odczytuje savings ada 1000 lub account bo 300, a następnie kwoty do wypłaty; wypisuje withdrew 200 albo refused: i komunikat, a na końcu sformatowane konto.
Twój kod umieść w plikach Account.R i Savings.R. main.R zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.
Spróbuj swoich sił
source("Account.R")
source("Savings.R")
# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
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 = "")
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