I am developing a package which has the function forecast.myclass
. I want that function to work nicely with forecast
package. I.e. when forecast
package is loaded the code forecast(object)
should call forecast.myclass
from my package.
Since I need only generic definition of forecast
from the package forecast
, and I do not use any other function from the package forecast
I am reluctant to include it in the Depends. So I define the generic in my package in the following way:
##'
##' @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),...) {
Now everything works as expected when package forecast
is not loaded. But when I load package forecast
, then forecast.midas_r
is not called, when doing forecast(object)
where object
is of class midas_r
. How should I solve this problem?
I'm not sure there's an easy solution to this. As others have said it's probably easiest to use Depends
to get around this, rather than redefining a generic method.
Here's a simple example which works for me. It's largely the same as your solution, but declaring @export
means you won't need to manually update the NAMESPACE
file.
##' @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")
. Put file mean.R
with the above contents in the directory /R
of the package.
Ensure you're in the directory 1 level below, then
roxygenize("newPkg", roxygen.dir="newPkg", copy.package=F, unlink.target=F)
Now
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)
I realize mean
is a function in base
but I have tested this for modifying generic functions elsewhere to give them a new method, so it should extend to your more general case also.
The problem here is that your definition of the forecast
generic is masking the definition from the forecast package, and your method is associated with your generic rather than the forecast package generic; this is just a complicated instance of two packages defining functions of the same name. The solution is to bite the bullet and Depend: on forecast, or when at the command line and both your package and forecast are attached fully resolve the function mypackage::forecast()
, or Import: forecast but not make the forecast generic available to the end user except by having them require(forecast)
(this might be appropriate if forecast
functionality were somehow peripheral to your package, e.g., plotting in 3D when plotting in 2D was sufficient).
For what it's worth, an S4 method in PkgB defined and exported on an imported S4 generic from PkgA implicitly exposes the S4 generic to the user, so the generic is available even if Imports: PkgA is specified in the DESCRIPTION file of PkgB.
One possible solution is to forcefully export forecast.midas_r. This means manually updating NAMESPACE
with export(forecast.midas_r)
everytime after check("yourpackagename")
.
What this does is make forecast.midas_r
visible for package forecast. If forecast.midas_r
is not exported, and exists only in the namespace of the package, then when package forecast is loaded, the generic forecast
is overwritten with the identical function from package forecast. So when forecast
is invoked on unknown object, R looks up for corresponding methods in package forecast and in general workspace. Since forecast.midas_r
is a private method R does not find it and produces an error.
This is not a perfect solution, since you need to manually update NAMESPACE
, but it is a solution nevertheless.
来源:https://stackoverflow.com/questions/18513607/how-to-extend-s3-method-from-another-package-without-loading-the-package