Menu
Coddy logo textTech

Fundamentos de NextMethod

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

Dentro de um método, NextMethod() chama o próximo método na sequência para o mesmo genérico, com os mesmos argumentos. Para um objeto com uma classe, o próximo método é o padrão, portanto um método pode reutilizar a resposta geral e acrescentar algo a ela:

describe <- function(x) UseMethod("describe")
describe.default <- function(x) paste("an object with", length(x), "fields")
describe.task <- function(x) paste0(NextMethod(), ", titled ", x$title)
t <- structure(list(title = "Buy milk", done = FALSE), class = "task")
print(describe(t))

Saída:

[1] "an object with 2 fields, titled Buy milk"

Um objeto pode ter várias classes em um vetor, como c("urgent", "task"). O despacho tenta cada uma na ordem, e NextMethod() no primeiro método passa para o método da próxima classe:

describe <- function(x) UseMethod("describe")
describe.task <- function(x) paste("task:", x$title)
describe.urgent <- function(x) paste("URGENT", NextMethod())
fix <- structure(list(title = "Fix the leak"), class = c("urgent", "task"))
print(describe(fix))

Saída:

[1] "URGENT task: Fix the leak"

NextMethod() transmite todos os argumentos recebidos pelo método, incluindo os extras, como sep. O próximo método vê os mesmos valores sem que você precise listá-los novamente:

label <- function(x, sep = ": ") UseMethod("label")
label.default <- function(x, sep = ": ") paste0("item", sep, x$name)
label.box <- function(x, sep = ": ") paste0("[", NextMethod(), "]")
b <- structure(list(name = "tools"), class = "box")
print(label(b))
print(label(b, sep = " = "))

Saída:

[1] "[item: tools]"
[1] "[item = tools]"

O R base usa NextMethod() para manter uma classe quando um vetor é submetido a subconjunto. O [ padrão remove a classe, portanto um método "[.percent" permite que ele faça o trabalho e coloque a classe de volta:

format.percent <- function(x, ...) paste0(unclass(x) * 100, "%")
"[.percent" <- function(x, i) structure(NextMethod(), class = "percent")
p <- structure(c(0.1, 0.25, 0.5), class = "percent")
print(format(p[2:3]))

Saída:

[1] "25%" "50%"
challenge icon

Desafio

Fácil

Tarefas e tarefas urgentes são duas classes em dois arquivos. Em Task.R, complete o método genérico describe(), o método padrão, que retorna an item, e describe.task(), que retorna an item: Buy milk chamando NextMethod() e adicionando o título. Em Urgent.R, complete describe.urgent(), que retorna URGENT an item: Fix bug chamando NextMethod().

Os construtores são fornecidos: uma tarefa urgente tem a classe c("urgent", "task"). O código fornecido lê as linhas task Buy milk, urgent Fix bug ou qualquer outra palavra com um título, que se torna um objeto dessa classe, e imprime describe() para cada um.

Seu código deve ficar em Task.R e Urgent.R. main.R contém o código fornecido de entrada/saída e não pode ser editado.

Experimente você mesmo

source("Task.R")
source("Urgent.R")

# Código de entrada/saída fornecido: mantenha-o como está
input <- suppressWarnings(readLines(file("stdin")))
for (line in input) {
  kind <- sub(" .*", "", line)
  title <- sub("^[a-z]+ ", "", line)
  t <- if (kind == "urgent") new_urgent(title) else if (kind == "task") new_task(title) else structure(list(title = title), class = kind)
  cat(describe(t), "\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