Menu
CoddyTech

Creación de genéricos

Parte de la sección Programación orientada a objetos del Journey de R de Coddy. Lección 27 de 57.

Un genérico S4 se crea con setGeneric(). Su cuerpo de función es standardGeneric("name"), el equivalente de S4 de UseMethod(). setGeneric() devuelve el nombre del genérico, que se imprime cuando se llama en el nivel superior:

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

Salida:

[1] "area"

Envuelve la llamada en invisible() para que esa línea no aparezca en la salida. setMethod("area", "Circle", ...) después añade el método para una clase:

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)))

Salida:

3.141593 9

Un método tiene los mismos argumentos que su genérico. Cuando el genérico tiene ..., un método puede añadir sus propios argumentos con nombre después de ellos:

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))

Salida:

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

setMethod() necesita que el genérico ya exista, así que primero se carga el archivo con setGeneric(). Una llamada para una clase sin método se detiene con un error que 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)

Salida:

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

Desafío

Fácil

Las formas son clases S4 en tres archivos. En Shape.R, crea los genéricos area(shape) y perimeter(shape) con setGeneric(), envueltos en invisible(). En Circle.R y Square.R se declaran las clases; añade los métodos area y perimeter de cada una con setMethod().

El código proporcionado lee líneas circle 2 o square 3 e imprime circle: area 12.57, perimeter 12.57.

Tu código va en Shape.R, Circle.R y Square.R. main.R contiene el código de entrada/salida proporcionado y no se puede editar.

Pruébalo tú mismo

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

# Código de entrada/salida proporcionado: mantenlo 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 iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación orientada a objetos

Practica por tu cuenta: Compilador de R online