Klasy wirtualne
Część sekcji Programowanie obiektowe ścieżki R w Coddy. Lekcja 34 z 57.
Klasa wirtualna opisuje to, co łączy rodzinę klas, i nie może mieć własnych obiektów. Zadeklaruj ją za pomocą representation("VIRTUAL"); jej podklasy jak zwykle używają contains:
setClass("Shape", representation("VIRTUAL"))
setClass("Circle", contains = "Shape", slots = c(r = "numeric"))
setClass("Square", contains = "Shape", slots = c(side = "numeric"))
cat(isVirtualClass("Shape"), is(new("Circle", r = 1), "Shape"), "\n")
cat(tryCatch({ new("Shape"); "made" }, error = function(e) "not allowed"), "\n")Wynik:
TRUE TRUE
not allowed Metoda dla klasy wirtualnej działa dla każdej podklasy. Tutaj describe() dla Shape wywołuje area(), którą implementuje każda podklasa, dzięki czemu opis jest zapisany tylko raz:
setClass("Shape", representation("VIRTUAL"))
setClass("Circle", contains = "Shape", slots = c(r = "numeric"))
setClass("Square", contains = "Shape", slots = c(side = "numeric"))
invisible(setGeneric("area", function(s) standardGeneric("area")))
invisible(setGeneric("describe", function(s) standardGeneric("describe")))
setMethod("area", "Circle", function(s) pi * s@r^2)
setMethod("area", "Square", function(s) s@side^2)
setMethod("describe", "Shape", function(s) sprintf("%s with area %.2f", class(s), area(s)))
for (s in list(new("Circle", r = 1), new("Square", side = 2))) cat(describe(s), "\n")Wynik:
Circle with area 3.14
Square with area 4.00 Klasa wirtualna może deklarować sloty, które mają potem wszystkie jej podklasy:
setClass("Shape", representation("VIRTUAL", label = "character"))
setClass("Square", contains = "Shape", slots = c(side = "numeric"))
sq <- new("Square", label = "tile", side = 2)
print(slotNames("Square"))Wynik:
[1] "side" "label"setClassUnion() tworzy klasę wirtualną z istniejących klas. Slot tego typu akceptuje dowolną z nich, na przykład kontakt będący adresem e-mail lub numerem telefonu:
setClassUnion("Contact", c("character", "numeric"))
setClass("Friend", slots = c(name = "character", contact = "Contact"))
a <- new("Friend", name = "Ada", contact = "ada@x.org")
b <- new("Friend", name = "Bo", contact = 5550123)
cat(class(a@contact), class(b@contact), "\n")
cat(tryCatch({ new("Friend", name = "Cy", contact = TRUE); "ok" }, error = function(e) "refused"), "\n")Wynik:
character numeric
refused Wyzwanie
ŁatwyPłatności współdzielą klasę wirtualną Payment (slot amount) oraz funkcje generyczne fee() i receipt(), wszystkie w pliku Payment.R. Uzupełnij:
- w pliku
Payment.Rmetodęreceipt()dla klasyPayment:card: 100.00 + 2.00 fee, zbudowaną z nazwy klasy zapisanej małymi literami, wartościamountifee(); - w pliku
Card.RklasęCard(zawieraPayment) i jej metodęfee(): 2% kwoty; - w pliku
Cash.RklasęCashi jej metodęfee(): 0.
Dostarczony kod odczytuje wiersze card 100 lub cash 20, wyświetla każdy paragon oraz łączną kwotę do zapłaty, a następnie sprawdza, czy Payment jest klasą wirtualną i nie można jej utworzyć.
Twój kod umieść w plikach Payment.R, Card.R i Cash.R. Plik main.R zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.
Spróbuj swoich sił
source("Payment.R")
source("Card.R")
source("Cash.R")
# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
input <- suppressWarnings(readLines(file("stdin")))
total <- 0
for (line in input) {
p <- strsplit(line, " ")[[1]]
amount <- as.numeric(p[2])
pay <- switch(p[1], card = new("Card", amount = amount), cash = new("Cash", amount = amount))
cat(receipt(pay), "\n", sep = "")
total <- total + amount + fee(pay)
}
cat(sprintf("charged: %.2f", total), "\n", sep = "")
cat("Payment is virtual: ", isVirtualClass("Payment"), "\n", sep = "")
cat(tryCatch({ new("Payment", amount = 1); "created a Payment" }, error = function(e) "cannot create a Payment"), "\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 – parkometr7S4 Dziedziczenie
Rozszerzanie za pomocą containscallNextMethodKlasy wirtualneSprawdzanie typów za pomocą is()Podsumowanie — opiekun zoo2Generics 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