Внутренняя работа `NextMethod()`

Я пытаюсь понять, как NextMethod() работает. Наиболее подробное объяснение, которое я нашел для системы классов S3, содержится в Статистических моделях Chambers & Hastie (edts.) В S (1993, Chapman & Hall), однако я нахожу часть, касающуюся NextMethod вызов немного неясен. Ниже приведены соответствующие параграфы, которые я пытаюсь понять (стр. 268-269).

Обратимся теперь к методам, вызываемым в результате вызова NextMethod() они ведут себя так, как если бы они были вызваны из предыдущего метода с помощью специального вызова. Аргументы в вызове унаследованного метода совпадают по количеству, порядку и фактическим именам аргументов с аргументами в вызове текущего метода (и, следовательно, в вызове универсального). Однако выражения для аргументов - это имена соответствующих формальных аргументов текущего метода. Предположим, например, что выражение print(ratings) вызвал метод print.ordered(), Когда этот метод вызывает NextMethod(), это эквивалентно вызову print.factor() формы print.factor(x), где x здесь x в рамках print.ordered(), Если несколько аргументов соответствуют формальному аргументу ... "эти аргументы представлены в вызове унаследованного метода y специальных имен" ..1 ", " ..2 "и т. д. Оценщик распознает эти имена и обращается с ними надлежащим образом (см. пример на стр. 476).

Это довольно тонкое определение существует, чтобы гарантировать, что семантика вызовов функций в S максимально точно переносится на использование методов (сравните Becker, Chambers и Wilks's The New S Language, стр. 354). Особенно:

  • Аргументы передаются от текущего метода к унаследованному методу с их текущими значениями в то время NextMethod() называется.
  • Ленивая оценка продолжается в силе; Неоцененные аргументы остаются неоцененными.
  • Отсутствующие аргументы остаются отсутствующими в унаследованном методе.
  • Аргументы прошли через ... msgstr "формальный аргумент получен с правильным именем аргумента.
  • Объекты в кадре, которые не соответствуют фактическим аргументам в вызове, не будут переданы унаследованному методу."

Процесс наследования по сути прозрачен, насколько аргументы идут.

Две вещи, которые я нахожу запутанными:

  1. Что такое "текущий метод" и что такое "предыдущий метод"?
  2. В чем разница между "аргументами в вызове унаследованного метода", "выражениями для аргументов" и "именами соответствующих формальных аргументов текущего метода"?

Вообще говоря, если бы кто-нибудь мог, пожалуйста, переформулировать описание, приведенное в вышеприведенных абзацах, более благоразумно.

2 ответа

Решение

Трудно пройти весь этот пост, но я думаю, что этот небольшой пример может помочь мистифицировать следующий метод диспетчеризации.

Я создаю объект с двумя атрибутами классов (наследование) "первый" и "второй".

x <- 1
attr(x,'class') <- c('first','second')

Затем я создаю generic метод Cat напечатать мой объект

Cate <- function(x,...)UseMethod('Cate')

Я определяю Cate метод для каждого класса.

Cate.first <- function(x,...){
  print(match.call())
  print(paste('first:',x))
  print('---------------------')
  NextMethod()                ## This will call Cate.second
}

Cate.second <- function(x,y){
  print(match.call())
  print(paste('second:',x,y))
}

Теперь вы можете проверить Cate позвоните, используя этот пример:

 Cate(x,1:3)
Cate.first(x = x, 1:3)
[1] "first: 1"
[1] "---------------------"
Cate.second(x = x, y = 1:3)  
[1] "second: 1 1" "second: 1 2" "second: 1 3"
  • Для Cate.second предыдущий метод - Cate.first.
  • Аргументы x и y передаются от текущего метода к унаследованному методу с их текущими значениями во время вызова NextMethod().
  • Аргумент y прошел через формальный аргумент "..." и получил правильное имя аргумента Cate.second(x = x, y = 1:3)

Рассмотрим этот пример, где универсальная функция f называется и вызывает f.ordered а затем, используя NextMethod, f.ordered Запускает f.factor:

f <- function(x) UseMethod("f")  # generic
f.ordered <- function(x) { x <- x[-1]; NextMethod() }
f.factor <- function(x) x # inherited method
x <- ordered(c("a", "b", "c"))

class(x)
## [1] "ordered" "factor" 

f(x)
## [1] b c
## Levels: a < b < c

Теперь рассмотрим оригинальный текст:

Обращаясь теперь к методам, вызываемым в результате вызова NextMethod(), они ведут себя так, как если бы они были вызваны из предыдущего метода с помощью специального вызова.

Вот f звонки f.ordered какие звонки f.factor поэтому метод "вызван в результате вызова NextMethod" f.factor и предыдущий методf.ordered,

Аргументы в вызове унаследованного метода совпадают по количеству, порядку и фактическим именам аргументов с аргументами в вызове текущего метода (и, следовательно, в вызове универсального). Однако выражения для аргументов - это имена соответствующих формальных аргументов текущего метода. Предположим, например, что выражение print(рейтинги) вызвало метод print.ordered(). Когда этот метод вызывает NextMethod(), это эквивалентно вызову print.factor() в форме print.factor(x), где x здесь x в рамке print.ordered ()

Теперь мы меняем перспективы и сидим в f.ordered а сейчас f.orderedтекущий метод и f.factor это унаследованный метод.

В тот момент, когда f.ordered Запускает NextMethod() специальный вызов построен для вызова f.factor чьи аргументы такие же, как аргументы, переданные f.ordered и в общем fза исключением того, что они ссылаются на версии аргументов в f.ordered (что имеет значение здесь как f.ordered изменяет аргумент перед вызовомf.factor,

Другие вопросы по тегам