2013-08-29 8 views
12

Ich entwickle ein Paket mit der Funktion forecast.myclass. Ich möchte, dass diese Funktion gut mit forecast Paket funktioniert. I.e. Wenn forecast Paket geladen ist, sollte der Code forecast(object)forecast.myclass von meinem Paket anrufen.So erweitern Sie die S3-Methode von einem anderen Paket, ohne das Paket zu laden

Da ich nur allgemeine Definition von forecast aus dem Paket forecast brauche, und ich verwende keine andere Funktion aus dem Paket forecast Ich bin nur ungern in der Hängt aufzunehmen. So definiere ich die generische in meinem Paket auf folgende Weise:

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

Jetzt ist alles wie erwartet funktioniert, wenn Paket forecast nicht geladen ist. Aber wenn ich das Paket forecast lade, dann wird forecast.midas_r nicht aufgerufen, wenn forecast(object) tut, wobei object der Klasse midas_r ist. Wie soll ich dieses Problem lösen?

+1

Sofern Sie 'prognose.midas_r' (was Sie nicht sind) dokumentieren, brauchen Sie nur' @ S3method (forcast, midas_r) '- das wird keine Rd-Datei erstellen, sondern die richtige Zeile zum NAMESPACE hinzufügen (Das ist der erste Ort, um zu sehen, wenn Sie Probleme haben) – hadley

+0

@hadley Ich dokumentiere die Prognose.midas_r in einer Weise, dass Vorhersage und Prognose.midas_r die gleiche Hilfeseite teilen. Der Code ist hier: https://github.com/mpiktas/midasr/blob/master/R/midas_r_methods.R, beginnt bei Zeile 279 – mpiktas

Antwort

4

Das Problem hier ist, dass Ihre Definition der forecast generische maskiert die Definition aus dem Prognosepaket, und Ihre Methode ist mit Ihrem generischen und nicht das generische Prognosepaket verbunden; Dies ist nur eine komplizierte Instanz von zwei Paketen, die gleichnamige Funktionen definieren. Die Lösung besteht darin, den Bullet zu beißen und zu dependen: bei Prognose, oder wenn an der Befehlszeile sowohl Ihr Paket als auch Ihre Prognose angefügt sind, lösen Sie die Funktion mypackage::forecast(), oder Import: Forecast, aber nicht die Prognose generic für den Endbenutzer verfügbar Sie haben require(forecast) (dies könnte angebracht sein, wenn forecast Funktionalität periphere zu Ihrem Paket, z. B. Plotten in 3D, wenn das Zeichnen in 2D war ausreichend).

Eine S4-Methode in PkgB, die auf einem importierten S4-Generic aus PkgA definiert und exportiert wird, stellt implizit den S4 generic dem Benutzer zur Verfügung, so dass der generische auch verfügbar ist, wenn Imports: PkgA in der DESCRIPTION-Datei von angegeben ist PkgB.

3

Eine mögliche Lösung ist Forecast.midas_r mit Nachdruck zu exportieren. Dies bedeutet, dass NAMESPACE mit export(forecast.midas_r) jedesmal nach check("yourpackagename") manuell aktualisiert wird.

Was das macht ist machen forecast.midas_r sichtbar für Paket Vorhersage. Wenn forecast.midas_r nicht exportiert wird und nur im Namespace des Pakets vorhanden ist, wird das Paket Forecast geladen, und das generische forecast wird mit der identischen Funktion aus dem Paket Prognose überschrieben. Wenn also forecast für unbekanntes Objekt aufgerufen wird, sucht R nach entsprechenden Methoden im Paket Prognose und im allgemeinen Arbeitsbereich. Da forecast.midas_r eine private Methode ist, findet R es nicht und erzeugt einen Fehler.

Dies ist keine perfekte Lösung, da Sie NAMESPACE manuell aktualisieren müssen, aber es ist dennoch eine Lösung.

7

Ich bin mir nicht sicher, dass es eine einfache Lösung dafür gibt. Wie andere gesagt haben, ist es wahrscheinlich am einfachsten, Depends zu verwenden, um dies zu umgehen, anstatt eine generische Methode neu zu definieren.

Hier ist ein einfaches Beispiel, das für mich funktioniert. Es ist weitgehend das gleiche wie Ihre Lösung, aber die Deklaration @export bedeutet, dass Sie die Datei NAMESPACE nicht manuell aktualisieren müssen.

##' @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) 
} 

Dann package.skeleton("newPkg"). Setzen Sie die Datei mean.R mit den obigen Inhalten in das Verzeichnis /R des Pakets.

Vergewissern Sie sich im Verzeichnis 1-Ebene sind unten, dann

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

Jetzt

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) 

Ich weiß, mean eine Funktion in base ist, aber ich habe an anderer Stelle zur Modifizierung von generischen Funktionen getestet, um Geben Sie ihnen eine neue Methode, also sollte sie auch auf Ihren allgemeineren Fall ausgedehnt werden.