如何在不加载包的情况下从另一个包扩展S3方法

时间:2013-08-29 14:23:48

标签: r devtools roxygen2

我正在开发一个具有函数forecast.myclass的包。我希望该函数与forecast包很好地协同工作。即加载forecast包时,代码forecast(object)应从我的包中调用forecast.myclass

由于我只需要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) objectmidas_r时不会被调用。我该如何解决这个问题?

3 个答案:

答案 0 :(得分:8)

我不确定这是一个简单的解决方案。正如其他人所说,使用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)
}

然后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)

我意识到meanbase中的一个函数,但我已经测试了这个函数用于修改其他地方的泛型函数以给它们一个新方法,所以它应该扩展到更一般的情况。

答案 1 :(得分:5)

这里的问题是,您对forecast泛型的定义是屏蔽预测包中的定义,并且您的方法与您的通用而非预测包通用相关联;这只是定义同名函数的两个包的复杂实例。解决方案是咬住子弹并依赖:预测,或者在命令行,并且您的包和预测都完全解析了函数mypackage::forecast(),或者导入:预测但不能使预测通用可用于最终用户除了拥有require(forecast)之外(如果forecast功能在某种程度上是您的包的外围,这可能是合适的,例如,在2D绘图时以3D绘图就足够了。)

对于它的价值,在PkgB中定义并从PkgA导入的S4泛型中导出的S4方法隐式地将S4泛型公开给用户,因此即使在PkgB的DESCRIPTION文件中指定了Imports:PkgA,该泛型也可用。

答案 2 :(得分:2)

一种可能的解决方案是强制导出forecast.midas_r。这意味着在NAMESPACE之后每次都export(forecast.midas_r)手动更新check("yourpackagename")

这样做可以使包预测forecast.midas_r可见。如果forecast.midas_r未导出且仅存在于包的命名空间中,则在加载包 forecast 时,将使用包<中的相同函数覆盖通用forecast EM>预测。因此,当在未知对象上调用forecast时,R会在包 forecast 和一般工作空间中查找相应的方法。由于forecast.midas_r是私有方法,因此R找不到它并产生错误。

这不是一个完美的解决方案,因为您需要手动更新NAMESPACE,但它仍然是一个解决方案。