Classes virtuelles
Fait partie de la section Programmation orientée objet du Journey R de Coddy. Leçon 34 sur 57.
Une classe virtuelle décrit ce qu’une famille de classes a en commun et ne peut pas avoir ses propres objets. Déclarez-la avec representation("VIRTUAL") ; ses sous-classes utilisent contains comme d’habitude :
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")Sortie :
TRUE TRUE
not allowed Une méthode pour la classe virtuelle fonctionne pour chaque sous-classe. Ici, describe() pour Shape appelle area(), que chaque sous-classe implémente, donc la description n’est écrite qu’une seule fois :
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")Sortie :
Circle with area 3.14
Square with area 4.00 Une classe virtuelle peut déclarer des slots, que chaque sous-classe possède ensuite :
setClass("Shape", representation("VIRTUAL", label = "character"))
setClass("Square", contains = "Shape", slots = c(side = "numeric"))
sq <- new("Square", label = "tile", side = 2)
print(slotNames("Square"))Sortie :
[1] "side" "label"setClassUnion() crée une classe virtuelle à partir de classes existantes. Un slot de ce type accepte n’importe laquelle d’entre elles, comme un contact qui est soit une adresse e-mail, soit un numéro de téléphone :
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")Sortie :
character numeric
refused Défi
FacileLes paiements partagent la classe virtuelle Payment (slot amount) et les génériques fee() et receipt(), tous définis dans Payment.R. Complétez :
- dans
Payment.R, la méthodereceipt()pourPayment:card: 100.00 + 2.00 fee, construite à partir du nom de classe en minuscules, deamountet defee(); - dans
Card.R, la classeCard(qui contientPayment) et sonfee(): 2 % du montant ; - dans
Cash.R, la classeCashet sonfee(): 0.
Le code fourni lit les lignes card 100 ou cash 20, affiche chaque reçu et le montant total facturé, puis vérifie que Payment est virtuelle et ne peut pas être créée.
Votre code doit être placé dans Payment.R, Card.R et Cash.R. main.R contient le code d’entrée/sortie fourni et ne peut pas être modifié.
Essayez vous-même
source("Payment.R")
source("Card.R")
source("Cash.R")
# Code d'entrée/sortie fourni : le garder tel quel
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 = "")
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation orientée objet
1Bases de S3
Travailler avec les fichiersListes avec une classeFonctions constructricesMéthodes print et formatValidateurs et fonctions utilitairesRécapitulatif - Températures4Encapsulation dans R
Les fermetures comme objetsLes environnements comme objetsFonctions d’accèsProtéger l’étatRécapitulatif - Parcmètre7S4 Héritage
Extension avec containscallNextMethodClasses virtuellesVérifier les types avec is()Récapitulatif - Gardien de zoo2S3 : génériques et méthodes
Génériques et UseMethodMéthodes par défautMéthodes pour les génériques de baseNotions de base sur NextMethodRécapitulatif - Aires des formes5Classes S4
Définir des classes S4Slots et accèsVérifications de validitéMéthodes showRécapitulatif - Catalogue de produits8Classes de référence
Définition des classes de référenceMéthodes et mises à jour des champsSémantique de copieHéritage et callSuperRécapitulatif - File d’attente des tâches11Projet : gestion de bibliothèque
Livres et membresEmprunter des livres3Héritage S3
Vecteurs de classesOrdre de recherche des méthodesÉtendre avec NextMethodVérifier avec inherits()Récapitulatif - Paie du personnelEntraînez-vous par vous-même : Compilateur R en ligne