R6类S4调度行为的不一致性 实际问题

R6类S4调度行为的不一致性 实际问题,r,inheritance,s4,reference-class,r6,R,Inheritance,S4,Reference Class,R6,类继承自(非正式的S3)类R6这一事实不应该允许为该类的签名参数定义S4方法吗 由于事实并非如此,在这种情况下,什么是符合当前S3/S4标准或在某种程度上可以被视为“最佳实践”的变通方法 背景和例子 参考类 考虑以下示例,其中您希望定义在所有实例继承自的超类上分派的方法(envRefClass): 但是,查看class generator对象的属性可以发现: > attributes(TestRefClass) [... omitted ...] Reference Superclas

类继承自(非正式的S3)类
R6
这一事实不应该允许为该类的签名参数定义S4方法吗

  • 由于事实并非如此,在这种情况下,什么是符合当前S3/S4标准或在某种程度上可以被视为“最佳实践”的变通方法

  • 背景和例子 参考类

    考虑以下示例,其中您希望定义在所有实例继承自的超类上分派的方法(
    envRefClass
    ):

    但是,查看class generator对象的属性可以发现:

    > attributes(TestRefClass)
    [... omitted ...]
    
     Reference Superclasses:  
        "envRefClass"
    
    [... omitted ...]
    
    这就是调度工作的原因

    R6类

    当您想为R6类做类似的事情时,事情似乎并不简单,即使它们最初看起来是这样(与参考类相比):

    R6Class()
    的帮助页面实际上揭示了class
    R6
    只是作为非正式的S3类添加的,只要
    class=TRUE
    。这也是为什么在尝试为此类定义S4方法时会出现警告的原因

    因此,这基本上给我们留下了两种可能的选择/解决方法:

  • 通过
    setOldClass()
  • 让R6类的所有实例从其他超类继承,例如,
    。R6
  • 广告1)

    当在类表/图中以S3风格进行黑客攻击时,这一点起作用:

    dummy <- structure("something", class = "R6")
    > foo(dummy)
    [1] "I'm the method for `R6`"
    
    广告2)


    .R6由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()))
    
    这是假设您已经定义了三个R6类(
    TestR6_1
    TestR6_3

    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(TestR6$new())
    [1] "TestR6" "R6"  
    
    setOldClass("R6")
    > isClass("R6")
    [1] TRUE
    
    dummy <- structure("something", class = "R6")
    > foo(dummy)
    [1] "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"’
    
    .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"’
    
    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()))
    
    .onLoad <- function(libname, pkgname) {
      setOldClass(c("TestR6_1", "R6"))
      setOldClass(c("TestR6_2", "R6"))
      setOldClass(c("TestR6_3", "R6"))
    }