我正在编写一个包,我有一个返回data.frame
类myclass
的函数。将它保存为data.frame非常重要,因此我将新类添加到对象中(下面的代码当然没有多大意义,但它仅用于说明):
foo <- function(x) {
df <- data.frame(a = x, b = "b", c = 1)
class(df) <- append(class(df), "myclass")
return(df)
}
test <- foo(1:3)
现在,我想为这个类创建一个S3方法:
plot.myclass <- function(x, ...) {
plot(a~b, data = test)
}
问题是,由于test
是data.frame
,plot(test)
会从包plot.data.frame
调用未导出的函数graphics
。
我试图通过将另一个(未导出的)函数定义为:
来解决这个问题plot.data.frame <- function(x, ...){
if ("myclass" %in% class(x)) plot.myclass(x, ...)
else graphics:::plot.data.frame(x, ...)
}
工作正常,但是devtools::check()
给了我一个警告,实际上:::
的文档说明了
在代码中使用:::通常是一个设计错误 相应的对象可能已经内部保持良好状态 原因。如果您有这种感觉,请考虑联系软件包维护人员 只需要检查就可以访问该对象。
解决这个问题的首选方法是什么?
我当然可以(i)摆脱data.frame
课程,但正如我所说,我更愿意保留它(ii)只需将plot.data.frame
的现有代码复制到最后一个函数的else
语句,或者(iii)简单地覆盖原始plot.data.frame
而忽略原始功能(绘制数据框) - 其中任何一个似乎都没有比我想象的更优雅有,但我确信有更好的解决方案。
任何见解都将受到赞赏。
答案 0 :(得分:4)
您希望'myclass'
在对象类中的'data.frame'
类之前来。这样,调度将首先查找<generic>.myclass
,如果找不到<generic>.data.frame
类通用的方法,则只查找'myclass'
。
要实现这一目标,您只需修改这一行
即可class(df) <- append(class(df), "myclass")
阅读
class(df) <- append(class(df), "myclass", after = 0)
但它同样易于使用
class(df) <- c('myclass', class(df))
对于后者,它非常明确,而append()
实际上是向后的,因为你需要 prepend 这个类。
对于更普遍的问题,没有一种方法可以在另一个包的命名空间中导入或使用非导出的方法或函数,而不会在检查包时生成各种警告。假设您不应该直接调用非导出函数(因为该函数不是供用户使用),并且任何尝试这样做都是打包代码的问题。