Wybór metody na podstawie dwóch argumentów
Część sekcji Programowanie obiektowe ścieżki R w Coddy. Lekcja 29 z 57.
Generyk S4 może wybierać swoją metodę na podstawie klas kilku argumentów. Sygnatura wymienia po jednej klasie dla każdego argumentu, więc każda para klas może mieć własną metodę:
setClass("Asteroid", slots = c(size = "numeric"))
setClass("Ship", slots = c(name = "character"))
invisible(setGeneric("collide", function(a, b) standardGeneric("collide")))
setMethod("collide", signature("Asteroid", "Ship"), function(a, b) paste(b@name, "is hit"))
setMethod("collide", signature("Ship", "Ship"), function(a, b) "two ships bump")
rock <- new("Asteroid", size = 3)
enterprise <- new("Ship", name = "Enterprise")
print(collide(rock, enterprise))
print(collide(enterprise, enterprise))Wynik:
[1] "Enterprise is hit"
[1] "two ships bump"Klasa "ANY" pasuje do każdej klasy. Metoda dla signature("ANY", "ANY") jest metodą awaryjną, która uruchamia się, gdy nie pasuje żadna bardziej szczegółowa para:
setClass("Ship", slots = c(name = "character"))
invisible(setGeneric("collide", function(a, b) standardGeneric("collide")))
setMethod("collide", signature("Ship", "Ship"), function(a, b) "two ships bump")
setMethod("collide", signature("ANY", "ANY"), function(a, b) "nothing happens")
s <- new("Ship", name = "A")
cat(collide(s, s), "/", collide(s, 42), "/", collide("x", "y"))Wynik:
two ships bump / nothing happens / nothing happensKolejność argumentów ma znaczenie: signature("A", "B") i signature("B", "A") to różne metody. Podstawowe klasy, takie jak numeric i character, również mogą pojawić się w sygnaturze:
invisible(setGeneric("join", function(x, y) standardGeneric("join")))
setMethod("join", signature("character", "numeric"), function(x, y) paste(x, "number", y))
setMethod("join", signature("numeric", "character"), function(x, y) paste(y, "after number", x))
print(join("item", 3))
print(join(3, "item"))Wynik:
[1] "item number 3"
[1] "item after number 3"Klasa "missing" w sygnaturze dopasowuje argument, który w ogóle nie został podany, więc jeden generyk może udostępniać krótką i długą formę:
invisible(setGeneric("greet", function(name, greeting) standardGeneric("greet")))
setMethod("greet", signature("character", "missing"), function(name, greeting) paste("Hello,", name))
setMethod("greet", signature("character", "character"), function(name, greeting) paste0(greeting, ", ", name))
print(greet("Ada"))
print(greet("Ada", "Good morning"))Wynik:
[1] "Hello, Ada"
[1] "Good morning, Ada"Wyzwanie
ŁatwyCeny wysyłki zależą od przedmiotu i strefy. Klasy są zadeklarowane w pliku Item.R (Letter, Box, każda z gniazdem kg) oraz Zone.R (Domestic, Abroad, każda z gniazdem name). W pliku Rates.R utwórz funkcję generyczną shipping(item, zone) i po jednej metodzie dla każdej pary:
Letterw kraju: 1; za granicą: 3.Boxw kraju: 5 plus 2 za kg; za granicą: 12 plus 4 za kg.- Każda inna para: przerwij działanie z komunikatem
no rate for this item and zone(użyjcall. = FALSE).
Dostarczony kod odczytuje wiersze box home 2.5 (przedmiot, strefa, kg), a nieznane słowa pozostają zwykłym tekstem, i wyświetla box to home: 10.00 lub error: oraz komunikat.
Twój kod umieść w plikach Item.R, Zone.R i Rates.R. Plik main.R zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.
Spróbuj swoich sił
source("Item.R")
source("Zone.R")
source("Rates.R")
# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
p <- strsplit(line, " ")[[1]]
kg <- as.numeric(p[3])
item <- switch(p[1], letter = new("Letter", kg = kg), box = new("Box", kg = kg), kg)
zone <- switch(p[2], home = new("Domestic", name = "home"), abroad = new("Abroad", name = "abroad"), p[2])
out <- tryCatch(sprintf("%s to %s: %.2f", p[1], p[2], shipping(item, zone)),
error = function(e) paste("error:", conditionMessage(e)))
cat(out, "\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ów6S4: Funkcje generyczne i metody
Tworzenie funkcji generycznychMetody dla typów wbudowanychWybór metody na podstawie dwóch argumentówsetValidity i validObjectPodsumowanie — pieniądze i walutaPoćwicz samodzielnie: Kompilator R online