Menu
Coddy logo textTech

Criando Genéricos

Parte da seção Programação Orientada a Objetos do Journey de R da Coddy. Lição 27 de 57.

Um genérico S4 é criado com setGeneric(). Seu corpo de função é standardGeneric("name"), o equivalente S4 de UseMethod(). setGeneric() retorna o nome do genérico, que é impresso quando ele é chamado no nível superior:

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

Saída:

[1] "area"

Envolva a chamada em invisible() para manter essa linha fora da saída. setMethod("area", "Circle", ...) então adiciona o método para uma 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)))

Saída:

3.141593 9

Um método tem os mesmos argumentos que seu genérico. Quando o genérico tem ..., um método pode adicionar seus próprios argumentos nomeados depois deles:

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

Saída:

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

setMethod() precisa que o genérico já exista, portanto o arquivo com setGeneric() é carregado primeiro. Uma chamada para uma classe sem um método interrompe a execução com um erro que informa a assinatura:

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

Saída:

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

Desafio

Fácil

As formas são classes S4 em três arquivos. Em Shape.R, crie os genéricos area(shape) e perimeter(shape) com setGeneric(), envolvidos em invisible(). Em Circle.R e Square.R, as classes são declaradas; adicione os métodos area e perimeter de cada uma com setMethod().

O código fornecido lê linhas circle 2 ou square 3 e imprime circle: area 12.57, perimeter 12.57.

Seu código deve estar em Shape.R, Circle.R e Square.R. main.R contém o código fornecido de entrada/saída e não pode ser editado.

Experimente você mesmo

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

# Código de entrada/saída fornecido: mantenha-o 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 iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Compilador de R online