Generics i UseMethod
Część sekcji Programowanie obiektowe ścieżki R w Coddy. Lekcja 7 z 57.
Funkcja generyczna to funkcja, której ciało zawiera UseMethod("name"). Gdy zostanie wywołana, sprawdza klasę swojego pierwszego argumentu i wywołuje metodę name.class. Funkcje print() i format() działają w ten sposób; możesz też napisać własne funkcje generyczne:
speak <- function(x) UseMethod("speak")
speak.dog <- function(x) paste(x$name, "says woof")
speak.cat <- function(x) paste(x$name, "says meow")
rex <- structure(list(name = "Rex"), class = "dog")
tom <- structure(list(name = "Tom"), class = "cat")
print(speak(rex))
print(speak(tom))Wynik:
[1] "Rex says woof"
[1] "Tom says meow"Wywołujący wykonuje jedno wywołanie, a każdy obiekt odpowiada na swój sposób. To polimorfizm: kod, który iteruje po mieszanej liście, nie potrzebuje instrukcji if dla każdej klasy:
speak <- function(x) UseMethod("speak")
speak.dog <- function(x) paste(x$name, "says woof")
speak.cat <- function(x) paste(x$name, "says meow")
pets <- list(structure(list(name = "Rex"), class = "dog"),
structure(list(name = "Tom"), class = "cat"),
structure(list(name = "Bo"), class = "dog"))
for (p in pets) cat(speak(p), "\n")Wynik:
Rex says woof
Tom says meow
Bo says woof Metoda przyjmuje argumenty funkcji generycznej. Dodaj do funkcji generycznej parametr ..., aby metody mogły przyjmować własne dodatkowe argumenty, takie jak digits dla koła:
area <- function(shape, ...) UseMethod("area")
area.square <- function(shape, ...) shape$side^2
area.circle <- function(shape, digits = 2, ...) round(pi * shape$r^2, digits)
sq <- structure(list(side = 3), class = "square")
ci <- structure(list(r = 1), class = "circle")
print(area(sq))
print(area(ci))
print(area(ci, digits = 4))Wynik:
[1] 9
[1] 3.14
[1] 3.1416UseMethod() przekazuje wywołanie metodzie i nigdy nie wraca: cokolwiek zwróci metoda, jest wynikiem funkcji generycznej, a kod po UseMethod() nie zostanie wykonany. Funkcja generyczna jest więc jednowierszowa:
size <- function(x) {
UseMethod("size")
cat("this line never runs\n")
}
size.box <- function(x) x$w * x$h
b <- structure(list(w = 2, h = 5), class = "box")
print(size(b))Wynik:
[1] 10Wyzwanie
ŁatwyKształty są rozdzielone między trzy pliki. Uzupełnij generyczną funkcję area() w pliku Shape.R, a następnie dodaj metody area.circle() (pi pomnożone przez kwadrat promienia) w pliku Circle.R oraz area.rectangle() (szerokość pomnożona przez wysokość) w pliku Rectangle.R. Konstruktory są już podane.
Dostarczony kod odczytuje wiersze circle 2 lub rectangle 3 4 i wypisuje klasę każdego kształtu oraz jego pole z dokładnością do dwóch miejsc po przecinku: circle: 12.57.
Twój kod umieść w plikach Shape.R, Circle.R i Rectangle.R. Plik main.R zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.
Spróbuj swoich sił
source("Shape.R")
source("Circle.R")
source("Rectangle.R")
# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
p <- strsplit(line, " ")[[1]]
s <- if (p[1] == "circle") new_circle(as.numeric(p[2])) else new_rectangle(as.numeric(p[2]), as.numeric(p[3]))
cat(sprintf("%s: %.2f", class(s), area(s)), "\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