2013-08-29 5 views
12

Я разрабатываю пакет, который имеет функцию forecast.myclass. Я хочу, чтобы эта функция прекрасно работала с пакетом forecast. То есть когда forecast пакет загружен, код forecast(object) должен позвонить forecast.myclass из моего пакета.Как расширить метод S3 из другого пакета без загрузки пакета

Поскольку мне нужно только родовое определение forecast из пакета forecast, и я не использую любые другие функции из пакета forecast я не хотел, чтобы включить его в Depends. Поэтому я определить общий в моем пакете следующим образом:

##' 
##' @export 
forecast <- function(object,...) UseMethod("forecast") 

##' @rdname forecast.midas_r 
##' @method forecast midas_r 
##' @export 
forecast.midas_r <- function(object,newdata=NULL,method=c("static","dynamic"),insample=get_estimation_sample(object),...) { 

Теперь все работает, как ожидается, когда пакет forecast не загружен. Но когда я загружаю пакет forecast, то forecast.midas_r не вызывается, когда forecast(object), где object имеет класс midas_r. Как мне решить эту проблему?

+1

Если вы не задокументируете 'прогноз.midas_r' (которого вы не являетесь), вам нужен только' @ S3method (forcast, midas_r) '- который не будет создавать Rd-файл, но добавит правильную строку в NAMESPACE (который является первым местом для поиска, если у вас возникли проблемы) – hadley

+0

@hadley Я документирую прогноз.midas_r таким образом, чтобы прогноз и прогноз.midas_r отображались на одной и той же странице справки. Код находится здесь: https://github.com/mpiktas/midasr/blob/master/R/midas_r_methods.R, начинается с строки 279 – mpiktas

ответ

4

Проблема заключается в том, что ваше определение генератора forecast маскирует определение из пакета прогноза, а ваш метод связан с вашим общим, а не с общим пакетом прогнозов; это всего лишь сложный экземпляр двух пакетов, определяющих функции с тем же именем. Решение состоит в том, чтобы укусить пулю и зависеть: от прогноза или когда в командной строке, а также ваш пакет и прогноз подключены, полностью разрешить функцию mypackage::forecast() или импортировать: прогноз, но не сделать общий доступ к прогнозу конечным пользователям, кроме как имея их require(forecast) (это может быть уместно, если функциональность forecast была чем-то периферической для вашего пакета, например, построение графика в 3D при построении графика в 2D).

Для того, что стоит, метод S4 в PkgB, определенный и экспортированный на импортированный S4 generic из PkgA, неявно предоставляет пользователю S4 общий характер, поэтому общий доступ доступен, даже если Imports: PkgA указан в файле DESCRIPTION PkgB.

3

Одним из возможных решений является принудительный экспорт прогноза.midas_r. Это означает, что вручную обновляется NAMESPACE с export(forecast.midas_r) каждый раз после check("yourpackagename").

Что это такое, делает forecast.midas_r видна для упаковки прогноз. Если forecast.midas_r не экспортируется и существует только в пространстве имен пакета, то при загрузке пакета общий forecast заменяется на идентичную функцию из пакета прогноз. Поэтому, когда forecast вызывается на неизвестном объекте, R ищет соответствующие методы в пакете прогноз и вообще рабочее пространство. Поскольку forecast.midas_r является частным методом, R не находит его и создает ошибку.

Это не идеальное решение, так как вам необходимо вручную обновить NAMESPACE, но это решение тем не менее.

7

Я не уверен, что это простое решение. Как говорили другие, возможно, проще всего использовать Depends, чтобы обойти это, а не переопределять общий метод.

Вот простой пример, который работает для меня. Это во многом то же самое, что и ваше решение, но объявление @export означает, что вам не нужно вручную обновлять файл NAMESPACE.

##' @name mean 
##' @export mean.newClass 
##' 
##' @method mean newClass 
##' 
##' @title mean for \code{newClass} object 
##' @param x A \code{newClass} object 
##' @param ... Additional arguments 
##' 
mean.newClass <- function(x, ...){ 
    stopifnot(class(x)=="newClass") 
    return(42) 
} 

Then package.skeleton("newPkg"). Поместите файл mean.R с указанным выше содержимым в каталог /R пакета.

Убедитесь, что вы находитесь в уровне каталога 1 ниже, а затем

roxygenize("newPkg", roxygen.dir="newPkg", copy.package=F, unlink.target=F) 

Теперь

library(devtools) 
dev_mode(on=TRUE) ### don't want to have to uninstall the package later 
install_local("newPkg") 
library(newPkg) 
x <- c(1,2) 
class(x) <- "newClass" 
stopifnot(mean(x)==42) 
stopifnot(mean(unclass(x))==1.5) 

Я понимаю, что mean функция в base, но я проверил это для изменения обобщенных функций в других местах дать им новый метод, поэтому он должен распространяться и на ваш более общий случай.

Смежные вопросы