实际问题
R6这一事实不应该允许为该类的签名参数定义S4方法吗?背景和实例
引用类
考虑下面的示例,您希望定义在所有https://stat.ethz.ch/R-manual/R-devel/library/methods/html/refClass.html实例从(envRefClass)继承的超类上调度的方法:
TestRefClass <- setRefClass("TestRefClass", fields= list(.x = "numeric"))
setGeneric("foo", signature = "x",
def = function(x) standardGeneric("foo")
)
setMethod("foo", c(x = "envRefClass"),
definition = function(x) {
"I'm the method for `envRefClass`"
})
> try(foo(x = TestRefClass$new()))
[1] "I'm the method for `envRefClass`"这种继承结构并不明显,因为class()不会揭示这一事实:
class(TestRefClass$new())
[1] "TestRefClass"
attr(,"package")
[1] ".GlobalEnv"但是,看看类生成器对象的属性就会发现:
> attributes(TestRefClass)
[... omitted ...]
Reference Superclasses:
"envRefClass"
[... omitted ...]这就是为什么调度工作的原因
R6类
当您想对R6类做类似的事情时,事情似乎并不直接,即使它们最初看起来是这样的(与引用类相比):
TestR6 <- R6Class("TestR6", public = list(.x = "numeric"))
setMethod("foo", c(x = "R6"),
definition = function(x) {
"I'm the method for `R6`"
})
> try(foo(x = TestR6$new()))
Error in (function (classes, fdef, mtable) :
unable to find an inherited method for function ‘foo’ for signature ‘"TestR6"’通过“直接出现”,我的意思是class()实际上建议所有R6类继承可用作方法分派的超类的类R6:
class(TestR6$new())
[1] "TestR6" "R6" R6Class()的帮助页面实际上显示,类R6只是作为一个非正式的S3类添加,就像class = TRUE一样。这也是为什么在试图为该类定义S4方法时会出现警告。
因此,这基本上给我们留下了两种可能的选择/解决办法:
R6将类setOldClass()转换为正式类.R6( Ad 1)
setOldClass("R6")
> isClass("R6")
[1] TRUE当侵入类表/图中的S3样式时,这是可行的:
dummy <- structure("something", class = "R6")
> foo(dummy)
[1] "I'm the method for `R6`"但是,对于实际的R6类实例,它失败了:
> try(foo(x = TestR6$new()))
Error in (function (classes, fdef, mtable) :
unable to find an inherited method for function ‘foo’ for signature ‘"TestR6"’(第二章)
.R6 <- R6Class(".R6")
TestR6_2 <- R6Class("TestR6_2", inherit = .R6, public = list(.x = "numeric"))
setMethod("foo", c(x = ".R6"),
definition = function(x) {
"I'm the method for `.R6`"
})
> try(foo(x = TestR6_2$new()))
Error in (function (classes, fdef, mtable) :
unable to find an inherited method for function ‘foo’ for signature ‘"TestR6_2"’结论
虽然方法1排序在一个“灰色区域”中操作,以使S3和S4在某种程度上兼容,但方法2似乎是一个完全有效的“纯S4”解决方案,海事组织应该能够工作。事实上,这并没有让我提出一个问题:在R6类的实现中,在非正式/正式类和方法分派的交互方面是否存在不一致。
发布于 2014-12-09 17:52:11
由于Hadley Wickham,我发现setOldClass()在包含继承结构时实际上解决了这个问题:
require("R6")
setOldClass(c("TestR6", "R6"))
TestR6 <- R6Class("TestR6", public = list(.x = "numeric"))
setGeneric("foo", signature = "x",
def = function(x) standardGeneric("foo")
)
setMethod("foo", c(x = "R6"),
definition = function(x) {
"I'm the method for `R6`"
})
try(foo(x = TestR6$new()))但是,AFAICT,这意味着对于您的包,您需要确保对您希望使用setOldClass()方法的所有R6类都以这种方式调用S4。
这可以通过在函数.onLoad()或.onAttach()中绑定这些调用来实现(参见here):
.onLoad <- function(libname, pkgname) {
setOldClass(c("TestR6_1", "R6"))
setOldClass(c("TestR6_2", "R6"))
setOldClass(c("TestR6_3", "R6"))
}这是假设您已经定义了三个R6类(TestR6_1通过TestR6_3)
https://stackoverflow.com/questions/27384772
复制相似问题