首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在保留继承的同时注册R6类的R6等价物

在保留继承的同时注册R6类的R6等价物
EN

Stack Overflow用户
提问于 2015-03-19 19:25:36
回答 1查看 470关注 0票数 2

实际问题

当所有类都需要驻留在包的名称空间(而不是在R6中)时,我如何将相互继承的一组S4类转换为S4类,同时保留继承结构?

详细信息

如果R6类是在.GlobalEnv中定义的(就像在使用source()进行采购时一样),并且setOldClass()也是用where = .GlobalEnv调用的,那么一切都可以正常工作。

但是,当在包的命名空间中定义了R6类(就像调用devtools::load_all()时),我无法让它工作:

在R6中定义.GlobalEnv

代码语言:javascript
复制
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的默认设置):

代码语言:javascript
复制
setOldClass(c("Object", "R6"))
setOldClass(c("Api", "Object"))
setOldClass(c("Module", "Api"))

当在包的命名空间中定义R6类时(比如当使用devtools::load_all()而不是source()时),我假设我需要提供一个显式的where来解释这个问题。

代码语言:javascript
复制
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 )才能再现错误

此外,这个单元测试可能有助于了解正在发生的事情。

EN

回答 1

Stack Overflow用户

发布于 2015-03-20 01:32:34

我想我搞清楚了。

汲取的经验教训

  1. setOldClass(c("Module", "Api"))失败的原因是包Rcpp具有定义相同名称的类。 要求(“R6”)>getClass(“模块”)类“模块”包"Rcpp“插槽:名称:.xData类:环境扩展:类".environment",直接类”环境“,按类".environment",距离2,带有显式强制类"refObject",按类".environment",距离3,带有显式强制
  2. 调用setOldClass()的最佳位置似乎在.onAttach()内部,因为在这个阶段,包已经完全加载,因此存在一个where参数可以指向的命名空间环境。 .onAttach <- as.environment(libname,pkgname) {其中<- as.environment("package:r6.s4") clss <- list( c("Object","R6"),c("Api","Object"),c("Module2","Api") )
  3. .onAttach()内部,您需要对以前的包加载时由setOldClass()设置的非“重载”类进行处理。这就是为什么这样的事情可能是有意义的: .onAttach <-函数(libname,pkgname) {其中<- as.environment("package:r6.s4") clss <- list( c("Object","R6"),c("Api","Object"),c("Module2","Api") ))}}
  4. 我喜欢R6的方法,它依赖于实际的生成器对象,而不是仅仅的类名很多,因为它使您能够使用::,从而使类与所有其他包组件一样有组织。但不幸的是,当通过S4为它们注册setOldClass()等价物时,这种模式似乎丢失了。这让我回想起我以前对类名称冲突 - *sigh*风险增加的抱怨。

对于那些对我的试错过程的细节感兴趣的人来说:我试着把这个包变成一种自我引用。检查文件R/classes.r .r测试/测试/测试-S4.r以及一些关于如何检查和处理名称冲突clashes.r的原型代码。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29153289

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档