实际问题
当所有类都需要驻留在包的名称空间(而不是在R6中)时,我如何将相互继承的一组S4类转换为S4类,同时保留继承结构?
详细信息
如果R6类是在.GlobalEnv中定义的(就像在使用source()进行采购时一样),并且setOldClass()也是用where = .GlobalEnv调用的,那么一切都可以正常工作。
但是,当在包的命名空间中定义了R6类(就像调用devtools::load_all()时),我无法让它工作:
在R6中定义.GlobalEnv类
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")使用setOldClass()调用where = .GlobalEnv (where的默认设置):
setOldClass(c("Object", "R6"))
setOldClass(c("Api", "Object"))
setOldClass(c("Module", "Api"))当在包的命名空间中定义R6类时(比如当使用devtools::load_all()而不是source()时),我假设我需要提供一个显式的where来解释这个问题。
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"),where = where):与“Module”不一致的旧式类信息;类是定义的,但没有扩展“Api”,并且作为数据部分无效。
促进生殖能力
我试图使这个问题尽可能容易重现,所以您可以在我的GitHub存储库上找到这个GitHub存储库包
请再次注意,您必须运行devtools::load_all() (或在RStudio中单击 CRTL + SHFT + L )才能再现错误。
此外,这个单元测试可能有助于了解正在发生的事情。
发布于 2015-03-20 01:32:34
我想我搞清楚了。
汲取的经验教训
setOldClass(c("Module", "Api"))失败的原因是包Rcpp具有定义相同名称的类。
要求(“R6”)>getClass(“模块”)类“模块”包"Rcpp“插槽:名称:.xData类:环境扩展:类".environment",直接类”环境“,按类".environment",距离2,带有显式强制类"refObject",按类".environment",距离3,带有显式强制setOldClass()的最佳位置似乎在.onAttach()内部,因为在这个阶段,包已经完全加载,因此存在一个where参数可以指向的命名空间环境。
.onAttach <- as.environment(libname,pkgname) {其中<- as.environment("package:r6.s4") clss <- list( c("Object","R6"),c("Api","Object"),c("Module2","Api") ).onAttach()内部,您需要对以前的包加载时由setOldClass()设置的非“重载”类进行处理。这就是为什么这样的事情可能是有意义的:
.onAttach <-函数(libname,pkgname) {其中<- as.environment("package:r6.s4") clss <- list( c("Object","R6"),c("Api","Object"),c("Module2","Api") ))}}R6的方法,它依赖于实际的生成器对象,而不是仅仅的类名很多,因为它使您能够使用::,从而使类与所有其他包组件一样有组织。但不幸的是,当通过S4为它们注册setOldClass()等价物时,这种模式似乎丢失了。这让我回想起我以前对类名称冲突 - *sigh*风险增加的抱怨。对于那些对我的试错过程的细节感兴趣的人来说:我试着把这个包变成一种自我引用。检查文件R/classes.r .r、测试/测试/测试-S4.r以及一些关于如何检查和处理名称冲突clashes.r的原型代码。
https://stackoverflow.com/questions/29153289
复制相似问题