在保留继承的同时注册R6类的S4等价物 实际问题
当所有类都需要存在于包的名称空间中时(而不是在在保留继承的同时注册R6类的S4等价物 实际问题,r,methods,namespaces,s4,r6,R,Methods,Namespaces,S4,R6,当所有类都需要存在于包的名称空间中时(而不是在GlobalEnv中),如何将相互继承的一组R6类转换为S4类,同时保留继承结构 细节 如果R6类已在.GlobalEnv中定义(就像使用source()进行寻源一样),并且setOldClass()也使用where=.GlobalEnv调用,那么一切都可以正常工作 但是,当R6类在包的命名空间中定义时(比如调用devtools::load_all()),我无法让它工作: 在.GlobalEnv中定义R6类: Object <- R6Class
GlobalEnv
中),如何将相互继承的一组R6类转换为S4类,同时保留继承结构
细节
如果R6类已在.GlobalEnv
中定义(就像使用source()
进行寻源一样),并且setOldClass()
也使用where=.GlobalEnv
调用,那么一切都可以正常工作
但是,当R6类在包的命名空间中定义时(比如调用devtools::load_all()
),我无法让它工作:
在.GlobalEnv
中定义R6类:
Object <- R6Class("Object", portable = TRUE, public = list(
foo = function() "foo")
)
Api <- R6Class("Api", inherit = Object, portable = TRUE,
public = list(bar = function() "bar")
)
Module <- R6Class("Module", inherit = Api, portable = TRUE,
public = list(fooBar = function() "fooBar")
当R6类在包的名称空间中定义时(如使用devtools::load_all()
而不是source()
“寻源”时),我假设我需要通过提供一个显式的where
:
setOldClass(c("Object", "R6"))
setOldClass(c("Api", "Object"))
setOldClass(c("Module", "Api"))
where <- if ("package:r6.s4" %in% search()) {
as.environment("package:r6.s4")
} else {
.GlobalEnv
}
try(setOldClass(c("Object", "R6"), where = where))
try(setOldClass(c("Api", "Object"), where = where))
try(setOldClass(c("Module", "Api"), where = where))
在哪里我想我找到了答案
经验教训
setOldClass(c(“模块”、“Api”)
失败的原因是因为包Rcpp
定义了一个具有相同名称的类
require("R6")
> getClass("Module")
Class "Module" [package "Rcpp"]
Slots:
Name: .xData
Class: environment
Extends:
Class ".environment", directly
Class "environment", by class ".environment", distance 2, with explicit coerce
Class "refObject", by class ".environment", distance 3, with explicit coerce
调用setOldClass()
的最佳位置似乎在.onAttach()
内,因为在此阶段包已完全加载,因此存在where
参数可以指向的命名空间环境
.onAttach <- function(libname, pkgname) {
where <- as.environment("package:r6.s4")
clss <- list(
c("Object", "R6"),
c("Api", "Object"),
c("Module2", "Api")
)
sapply(clss, function(cls) {
try(setOldClass(cls, where = where))
})
}
我喜欢R6
依赖于实际的生成器对象的方法,而不仅仅是类名很多,因为它使您能够使用:
,从而使类与所有其他包组件一样有组织。但不幸的是,当通过setOldClass()
为它们注册S4等价物时,这种范例似乎丢失了。这种情况让我又回到了我以前的抱怨,那就是——*叹气*
对于那些对我的试错过程的细节感兴趣的人来说:我试图把这个包变成一种自我参考。检查文件,以及一些关于如何检查和处理名称冲突的原型代码。我也有类似的情况。但是在我的包中,我为包中定义的类编写了一些方法(例如,在您的示例中,Api
和Module2
),用于在其他包中定义的通用S4函数(例如,sp::coordinates
),使用类似的东西:setMethod('coordinates',signature='Api'){…
)。这导致加载包时出错,因为类Api
在R
解析新方法时未注册。
.onAttach <- function(libname, pkgname) {
where <- as.environment("package:r6.s4")
clss <- list(
c("Object", "R6"),
c("Api", "Object"),
c("Module2", "Api")
)
sapply(clss, function(cls) {
idx <- sapply(cls, isClass)
try(sapply(cls[idx], removeClass, where = where))
try(setOldClass(cls, where = where))
})
}