Menu
Coddy logo textTech

Nozioni di base su NextMethod

Fa parte della sezione Programmazione orientata agli oggetti del percorso R di Coddy. Lezione 10 di 57.

All'interno di un metodo, NextMethod() chiama il metodo successivo in ordine per lo stesso generico, con gli stessi argomenti. Per un oggetto con una sola classe, il metodo successivo è quello predefinito, quindi un metodo può riutilizzare la risposta generale e aggiungervi qualcosa:

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

Output:

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

Un oggetto può avere diverse classi in un vettore, come c("urgent", "task"). Il dispatch le prova nell'ordine, e NextMethod() nel primo metodo passa al metodo per la classe successiva:

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

Output:

[1] "URGENT task: Fix the leak"

NextMethod() passa tutti gli argomenti ricevuti dal metodo, compresi quelli aggiuntivi come sep. Il metodo successivo vede gli stessi valori senza che tu debba elencarli di nuovo:

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

Output:

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

Base R usa NextMethod() per mantenere una classe quando si seleziona un sottoinsieme di un vettore. L'operatore predefinito [ rimuove la classe, quindi un metodo "[.percent" gli consente di eseguire il lavoro e ripristina la classe:

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

Output:

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

Sfida

Facile

Le attività e le attività urgenti sono due classi in due file. In Task.R completa la funzione generica describe(), il metodo predefinito, che restituisce an item, e describe.task(), che restituisce an item: Buy milk chiamando NextMethod() e aggiungendo il titolo. In Urgent.R completa describe.urgent(), che restituisce URGENT an item: Fix bug chiamando NextMethod().

I costruttori sono forniti: un’attività urgente ha la classe c("urgent", "task"). Il codice fornito legge righe come task Buy milk, urgent Fix bug o qualsiasi altra parola con un titolo, che diventa un oggetto di quella classe, e stampa describe() per ciascuna.

Il tuo codice va in Task.R e Urgent.R. main.R contiene il codice di input/output fornito e non può essere modificato.

Provalo tu

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

# Codice di input/output fornito: lascialo così com'è
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 iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore R online