How to extend S3 method from another package without loading the package

。_饼干妹妹 提交于 2019-11-30 11:35:12

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!