Despacho em Dois Argumentos
Parte da seção Programação Orientada a Objetos do Journey de R da Coddy. Lição 29 de 57.
Um genérico S4 pode escolher seu método pelas classes de vários argumentos. A assinatura lista uma classe por argumento, portanto cada par de classes pode ter seu próprio método:
setClass("Asteroid", slots = c(size = "numeric"))
setClass("Ship", slots = c(name = "character"))
invisible(setGeneric("collide", function(a, b) standardGeneric("collide")))
setMethod("collide", signature("Asteroid", "Ship"), function(a, b) paste(b@name, "is hit"))
setMethod("collide", signature("Ship", "Ship"), function(a, b) "two ships bump")
rock <- new("Asteroid", size = 3)
enterprise <- new("Ship", name = "Enterprise")
print(collide(rock, enterprise))
print(collide(enterprise, enterprise))Saída:
[1] "Enterprise is hit"
[1] "two ships bump"A classe "ANY" corresponde a todas as classes. Um método para signature("ANY", "ANY") é o fallback executado quando nenhum par mais específico se encaixa:
setClass("Ship", slots = c(name = "character"))
invisible(setGeneric("collide", function(a, b) standardGeneric("collide")))
setMethod("collide", signature("Ship", "Ship"), function(a, b) "two ships bump")
setMethod("collide", signature("ANY", "ANY"), function(a, b) "nothing happens")
s <- new("Ship", name = "A")
cat(collide(s, s), "/", collide(s, 42), "/", collide("x", "y"))Saída:
two ships bump / nothing happens / nothing happensA ordem dos argumentos é importante: signature("A", "B") e signature("B", "A") são métodos diferentes. Classes básicas como numeric e character também podem aparecer em uma assinatura:
invisible(setGeneric("join", function(x, y) standardGeneric("join")))
setMethod("join", signature("character", "numeric"), function(x, y) paste(x, "number", y))
setMethod("join", signature("numeric", "character"), function(x, y) paste(y, "after number", x))
print(join("item", 3))
print(join(3, "item"))Saída:
[1] "item number 3"
[1] "item after number 3"A classe "missing" em uma assinatura corresponde a um argumento que não foi fornecido, portanto, um genérico pode oferecer uma forma curta e uma forma longa:
invisible(setGeneric("greet", function(name, greeting) standardGeneric("greet")))
setMethod("greet", signature("character", "missing"), function(name, greeting) paste("Hello,", name))
setMethod("greet", signature("character", "character"), function(name, greeting) paste0(greeting, ", ", name))
print(greet("Ada"))
print(greet("Ada", "Good morning"))Saída:
[1] "Hello, Ada"
[1] "Good morning, Ada"Desafio
FácilOs preços de envio dependem do item e da zona. As classes são declaradas em Item.R (Letter, Box, cada uma com um slot kg) e em Zone.R (Domestic, Abroad, cada uma com um slot name). Em Rates.R, crie o genérico shipping(item, zone) e um método para cada par:
Letterem casa: 1; no exterior: 3.Boxem casa: 5 mais 2 por kg; no exterior: 12 mais 4 por kg.- Qualquer outro par: interrompa com
no rate for this item and zone(usecall. = FALSE).
O código fornecido lê linhas como box home 2.5 (item, zona, kg), nas quais palavras desconhecidas permanecem como texto simples, e imprime box to home: 10.00 ou error: e a mensagem.
Seu código deve estar em Item.R, Zone.R e Rates.R. main.R contém o código fornecido de entrada/saída e não pode ser editado.
Experimente você mesmo
source("Item.R")
source("Zone.R")
source("Rates.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]]
kg <- as.numeric(p[3])
item <- switch(p[1], letter = new("Letter", kg = kg), box = new("Box", kg = kg), kg)
zone <- switch(p[2], home = new("Domestic", name = "home"), abroad = new("Abroad", name = "abroad"), p[2])
out <- tryCatch(sprintf("%s to %s: %.2f", p[1], p[2], shipping(item, zone)),
error = function(e) paste("error:", conditionMessage(e)))
cat(out, "\n", sep = "")
}
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
1Fundamentos do S3
Trabalhando com ArquivosListas com uma ClasseFunções ConstrutorasMétodos de Impressão e FormataçãoValidadores e AuxiliaresRevisão - Temperaturas4Encapsulamento em R
Closures como ObjetosAmbientes como ObjetosFunções de AcessoProtegendo o EstadoRecapitulação - Parquímetro2Genéricos e Métodos S3
Genéricos e UseMethodMétodos padrãoMétodos para genéricos baseFundamentos de NextMethodRevisão - Áreas de formas5Classes S4
Definindo classes S4Slots e acessoVerificações de validadeMétodos showRevisão - Catálogo de produtos8Classes de Referência
Definindo Classes de ReferênciaMétodos e Atualizações de CamposSemântica de CópiaHerança e callSuperRecapitulação — Fila de Tarefas11Projeto: Gerenciamento de Biblioteca
Livros e MembrosEmpréstimo de Livros3Herança S3
Vetores de classeOrdem de busca de métodosEstendendo com NextMethodVerificando com inherits()Revisão - Folha de pagamento da equipe6S4 Genéricos e Métodos
Criando GenéricosMétodos para Objetos IntegradosDespacho em Dois ArgumentossetValidity e validObjectRevisão - Dinheiro e MoedaPratique por conta própria: Compilador de R online