Menu
Coddy logo textTech

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"), la contraparte 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 mantener esa línea fuera de 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, por lo que el archivo con setGeneric() se carga primero. Una llamada para una clase sin un 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(), encapsulados 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 las 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 proporcionado de entrada/salida y no se puede editar.

Pruébalo tú mismo

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

# Código de entrada/salida suministrado: 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 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