Menu
Coddy logo textTech

Основы NextMethod

Часть раздела Объектно-ориентированное программирование путешествия по R на Coddy. Урок 10 из 57.

Внутри метода NextMethod() вызывает следующий метод в цепочке для того же обобщённого метода с теми же аргументами. Для объекта с одним классом следующим методом является метод по умолчанию, поэтому метод может повторно использовать общий ответ и дополнить его:

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

Результат:

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

Объект может иметь несколько классов в векторе, например c("urgent", "task"). Диспетчеризация перебирает их по порядку, а NextMethod() в первом методе переходит к методу для следующего класса:

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

Вывод:

[1] "URGENT task: Fix the leak"

NextMethod() передаёт все аргументы, полученные методом, включая дополнительные, такие как sep. Следующий метод видит те же значения, и вам не нужно перечислять их снова:

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

Результат:

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

Base R использует NextMethod(), чтобы сохранять класс при выборе подмножества вектора. По умолчанию [ удаляет класс, поэтому метод "[.percent" позволяет ему выполнить эту работу и вернуть класс:

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

Результат:

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

Задание

Легко

Задачи и срочные задачи — это два класса в двух файлах. В Task.R реализуйте обобщённый метод describe(), метод по умолчанию, который возвращает an item, а также describe.task(), который возвращает an item: Buy milk, вызывая NextMethod() и добавляя заголовок. В Urgent.R реализуйте describe.urgent(), который возвращает URGENT an item: Fix bug, вызывая NextMethod().

Конструкторы уже предоставлены: срочная задача имеет класс c("urgent", "task"). Предоставленный код считывает строки task Buy milk, urgent Fix bug или любое другое слово с заголовком, которое становится объектом этого класса, и выводит describe() для каждого объекта.

Ваш код должен находиться в Task.R и Urgent.R. В main.R содержится предоставленный код ввода/вывода, и его нельзя изменять.

Попробуйте сами

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

# Предоставленный код ввода/вывода: оставьте его как есть
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 iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор R