2013-08-29 14 views
12

Pracuję nad pakietem, który ma funkcję forecast.myclass. Chcę, aby ta funkcja dobrze działała z pakietem forecast. To znaczy. po załadowaniu pakietu forecast kod forecast(object) powinien wywołać forecast.myclass z mojej paczki.Jak przedłużyć metodę S3 z innego pakietu bez ładowania pakietu

Ponieważ muszę tylko ogólną definicję forecast z pakietu forecast i nie używam żadnej innej funkcji z pakietu forecast Jestem niechętny, aby uwzględnić go w Zależy. Tak więc określenie rodzajowe w moim opakowaniu w następujący sposób:

##' 
##' @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),...) { 

Teraz wszystko działa zgodnie z oczekiwaniami, gdy pakiet forecast nie jest załadowany. Ale kiedy ładuję pakiet forecast, wtedy forecast.midas_r nie jest wywoływane, gdy robię forecast(object) gdzie object jest klasy midas_r. Jak mam rozwiązać ten problem?

+1

Jeśli nie dokumentujesz 'forecast.midas_r' (którego nie masz), potrzebujesz tylko' @ S3method (forcast, midas_r) '- który nie utworzy pliku Rd, ale doda poprawną linię do NAMESPACE (który jest pierwszym miejscem do sprawdzenia, jeśli masz problemy) – hadley

+0

@hadley Udokumentuję forecast.midas_r w sposób, w jaki prognoza i forecast.midas_r udostępniają tę samą stronę pomocy. Kod jest tutaj: https://github.com/mpiktas/midasr/blob/master/R/midas_r_methods.R, zaczyna się od linii 279 – mpiktas

Odpowiedz

4

Problem polega na tym, że twoja definicja generatora forecast maskuje definicję z pakietu prognozy, a twoja metoda jest powiązana z generycznym pakietem generycznym, a nie z generałem prognozy; jest to po prostu skomplikowana instancja dwóch pakietów definiujących funkcje o tej samej nazwie. Rozwiązaniem jest ugryźć punktor i Depend: w prognozie lub gdy w wierszu poleceń i zarówno pakiet jak i prognoza są załączone, należy całkowicie rozwiązać funkcję mypackage::forecast() lub Importuj: prognozę, ale nie udostępniaj prognozy generycznej użytkownikowi końcowemu, chyba że posiadanie ich require(forecast) (może to być odpowiednie, jeśli funkcja forecast była w jakiś sposób peryferyjna dla twojego pakietu, np., kreślenie w 3D, gdy drukowanie w 2D było wystarczające).

Dla tego, co jest warte, metoda S4 w PkgB zdefiniowana i wyeksportowana na zaimportowanym generatorze S4 z PkgA domyślnie naraża użytkownika generic S4, więc ogólny jest dostępny, nawet jeśli w pliku DESCRIPTION określono Imports: PkgA PkgB.

3

Jednym z możliwych rozwiązań jest wymuszenie eksportu prognozy.midas_r. Oznacza to ręczną aktualizację NAMESPACE za pomocą export(forecast.midas_r) za każdym razem po check("yourpackagename").

Co to powoduje, że forecast.midas_r jest widoczny dla pakietu , prognoza:. Jeśli forecast.midas_r nie zostanie wyeksportowany i istnieje tylko w przestrzeni nazw pakietu, wówczas gdy zostanie załadowany pakiet , prognoza, nazwa standardowa forecast zostanie zastąpiona identyczną funkcją z pakietu , prognoza. Więc kiedy forecast jest wywoływany na nieznanym obiekcie, R wyszukuje odpowiednie metody w pakiecie , prognozy oraz w ogólnym obszarze roboczym. Ponieważ forecast.midas_r jest prywatną metodą R, nie znajduje jej i powoduje błąd.

To nie jest idealne rozwiązanie, ponieważ trzeba ręcznie zaktualizować NAMESPACE, ale jest to jednak rozwiązanie.

7

Nie jestem pewien, czy jest na to łatwe rozwiązanie. Jak powiedzieli inni, najprawdopodobniej łatwiej jest ominąć tę kwestię, niż przedefiniować ogólną metodę.

Oto prosty przykład, który działa dla mnie. Jest w dużej mierze takie samo jak rozwiązanie, ale zadeklarowanie @export oznacza, że ​​nie trzeba ręcznie aktualizować pliku 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) 
} 

Następnie package.skeleton("newPkg"). Umieść plik mean.R z powyższą zawartością w katalogu /R pakietu.

Upewnij się, że jesteś na poziomie katalogu 1 poniżej, a następnie

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

Teraz

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) 

Zdaję sobie sprawę mean jest funkcją w base ale ja testowałem to dla modyfikacji funkcji rodzajowe gdzie indziej daj im nową metodę, więc powinna rozszerzyć się także na bardziej ogólną sprawę.

Powiązane problemy