Как вы расширяете rbind для данных.подкласс фреймов?
Мой вопрос в том, как вы расширяете rbind() для работы с подклассом data.frame? Я не могу должным образом расширить rbind() для работы даже с очень простым подклассом. Следующий пример демонстрирует эту проблему: 
Определение подкласса и метода:
new_df2 <- function(x, ...)
{
  stopifnot(is.data.frame(x))
  structure(x, class = c("df2", "data.frame"), author = "some user")
}
rbind.df2 <- function(..., deparse.level = 1)
{
  NextMethod()
}
Я понимаю, что расширение rbind() в этом случае не обязательно, но мой грандиозный план состоит в том, чтобы использовать rbind.data.frame() на моем подклассе, а затем добавить несколько дополнительных проверок/атрибутов к его результату. 
Если вы вызовете далее вы получаете ошибку: Error in NextMethod() : generic function not specified. 
Не работает:
t1 <- data.frame(a = 1:12, b = month.abb)
t2 <- new_df2(t1)
rbind(t2, t2)
Я также пытался использовать NextMethod(generic = "rbind"), но в этом случае вы получите эту ошибку: Error in NextMethod(generic = "rbind") : wrong value for .Method.
Также не работает:
rbind.df2 <- function(..., deparse.level = 1)
{
  NextMethod(generic = "rbind")
}
rbind(t2, t2)
Я нахожусь в тупике и догадываюсь о границах моего понимания подклассов / методов тоже. Спасибо за любую помощь.
2 ответа:
Я рассмотрю конкретный случай
rbind()ниже, но сначала отмечу, что мы могли бы генерировать дополнительные примеры, показывающие, что в общем случае нет проблем сNextMethod(), Когда первый аргумент...(относительно запроса на вознаграждение):f <- function(..., b = 3) UseMethod("f") f.a <- function(..., b = 3) { print("yes"); NextMethod() } f.integer <- function(..., b = 4) sapply(list(...), "*", b) x <- 1:10 class(x) <- c("a", class(x)) f(x) [1] "yes" [,1] [1,] 4 [2,] 8 [3,] 12 [4,] 16 [5,] 20 [6,] 24 [7,] 28 [8,] 32 [9,] 36 [10,] 40 f(x, b = 5) [1] "yes" [,1] [1,] 5 [2,] 10 [3,] 15 [4,] 20 [5,] 25 [6,] 30 [7,] 35 [8,] 40 [9,] 45 [10,] 50Так почему же не rbind?работа df2?
Как оказалось,
rbind()иcbind()не являются нормальными дженериками. Во-первых, они внутренне универсальны; смотрите раздел "внутренние универсалии" здесь из старого S3 Хэдли Уикхема страница на Advanced R, или эта выдержка из текущей Advanced R :Некоторые генераторы S3, такие как [, sum () и cbind (), не называют UseMethod() поскольку они реализованы в C. Вместо этого они вызывают функции C. DispatchGroup() или DispatchOrEval ().
Этого недостаточно, чтобы причинить нам неприятности, как мы можем видеть, используя
sum()в качестве примера:sum.a <- function(x, na.rm = FALSE) { print("yes"); NextMethod() } sum(x) [1] "yes" [1] 55Однако для
rbindиcbindэто еще более странно, как признается в комментариях в исходный код (начиная со строки 1025):/* cbind(deparse.level, ...) and rbind(deparse.level, ...) : */ /* This is a special .Internal */... (Код опущен) ...
После этого дается некоторое объяснение правил отправки, но до сих пор я не смог использовать эту информацию, чтобы заставить/* Lazy evaluation and method dispatch based on argument types are * fundamentally incompatible notions. The results here are * ghastly.NextMethod()работать. В случае использования, приведенном выше, я бы последовал совету F. Privé из комментариев и сделал это:new_df2 <- function(x, ...) { stopifnot(is.data.frame(x)) structure(x, class = c("df2", "data.frame")) } rbind.df2 <- function(..., deparse.level = 1) { print("yes") # Or whatever else you want/need to do base::rbind.data.frame(..., deparse.level = deparse.level) } t1 <- data.frame(a = 1:12, b = month.abb) t2 <- new_df2(t1) rbind(t2, t2) [1] "yes" a b 1 1 Jan 2 2 Feb 3 3 Mar 4 4 Apr 5 5 May 6 6 Jun 7 7 Jul 8 8 Aug 9 9 Sep 10 10 Oct 11 11 Nov 12 12 Dec 13 1 Jan 14 2 Feb 15 3 Mar 16 4 Apr 17 5 May 18 6 Jun 19 7 Jul 20 8 Aug 21 9 Sep 22 10 Oct 23 11 Nov 24 12 Dec
Ответ состоит в том, чтобы расширить
rbind2, а неrbind. На странице справки изrbind2:" это (S4) универсальные функции с методами по умолчанию.
...
Основное использование cbind2 (rbind2) заключается в рекурсивном вызове cbind () (rbind ()), когда выполняются оба этих требования:
Существует по крайней мере один аргумент, который является объектом S4, и
Сбой диспетчеризации S3 (см. раздел диспетчеризации в разделе cbind)."