Menu
Coddy logo textTech

Creare generici

Fa parte della sezione Programmazione orientata agli oggetti del percorso R di Coddy. Lezione 27 di 57.

Un generico S4 viene creato con setGeneric(). Il suo corpo della funzione è standardGeneric("name"), la controparte S4 di UseMethod(). setGeneric() restituisce il nome del generico, che viene stampato quando viene chiamato al livello superiore:

setGeneric("area", function(shape) standardGeneric("area"))

Output:

[1] "area"

Racchiudi la chiamata in invisible() per escludere quella riga dall'output. setMethod("area", "Circle", ...) aggiunge quindi il metodo per una classe:

setClass("Circle", slots = c(r = "numeric"))
setClass("Square", slots = c(side = "numeric"))
invisible(setGeneric("area", function(shape) standardGeneric("area")))
setMethod("area", "Circle", function(shape) pi * shape@r^2)
setMethod("area", "Square", function(shape) shape@side^2)
cat(area(new("Circle", r = 1)), area(new("Square", side = 3)))

Output:

3.141593 9

Un metodo ha gli stessi argomenti del suo generico. Quando il generico ha ..., un metodo può aggiungere i propri argomenti con nome dopo di essi:

setClass("Circle", slots = c(r = "numeric"))
invisible(setGeneric("describe", function(x, ...) standardGeneric("describe")))
setMethod("describe", "Circle", function(x, ..., digits = 2) {
  paste("circle of area", round(pi * x@r^2, digits))
})
c1 <- new("Circle", r = 2)
print(describe(c1))
print(describe(c1, digits = 4))

Output:

[1] "circle of area 12.57"
[1] "circle of area 12.5664"

setMethod() richiede che il generico esista già, quindi il file con setGeneric() viene caricato per primo. Una chiamata per una classe senza un metodo si interrompe con un errore che indica la firma:

invisible(setGeneric("area", function(shape) standardGeneric("area")))
setClass("Circle", slots = c(r = "numeric"))
setMethod("area", "Circle", function(shape) pi * shape@r^2)
area(42)

Output:

Error: unable to find an inherited method for function ‘area’ for signature ‘shape = "numeric"’
Execution halted
challenge icon

Sfida

Facile

Le forme sono classi S4 in tre file. In Shape.R crea i generici area(shape) e perimeter(shape) con setGeneric(), racchiusi in invisible(). In Circle.R e Square.R vengono dichiarate le classi; aggiungi i metodi area e perimeter di ciascuna con setMethod().

Il codice fornito legge righe circle 2 o square 3 e stampa circle: area 12.57, perimeter 12.57.

Il tuo codice va in Shape.R, Circle.R e Square.R. main.R contiene il codice di input/output fornito e non può essere modificato.

Provalo tu

source("Shape.R")
source("Circle.R")
source("Square.R")

# Código de entrada/salida proporcionado: déjalo tal como está
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  p <- strsplit(line, " ")[[1]]
  s <- if (p[1] == "circle") new("Circle", r = as.numeric(p[2])) else new("Square", side = as.numeric(p[2]))
  cat(sprintf("%s: area %.2f, perimeter %.2f", p[1], area(s), perimeter(s)), "\n", sep = "")
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore R online