【问题标题】:Using R6, how do I find classes and objects that inherit from some superclass?使用 R6,我如何找到从某个超类继承的类和对象?
【发布时间】:2017-07-07 01:31:29
【问题描述】:

假设我有:

Foo <- R6::R6Class("Foo")
Bar1 <- R6::R6Class("Bar1", inherit = "Foo")
Bar2 <- R6::R6Class("Bar2", inherit = "Foo")

f <- Foo$new()

A.我可以做类似的事情吗

R6::findChildren("Foo")
[1] "Bar1" "Bar2"

(我认为这与R, R6, Get Full Class Name from R6Generator Object 相同,但包括它是为了全面)

B.我可以做类似的事情吗

R6::findInstances("Foo")
[1] "f"

C.我可以做类似的事情吗

b1 <- Bar1$new()
b2 <- Bar2$new()
R6::findInstances("Foo")
[1] "f" "b1" "b2"

【问题讨论】:

    标签: r oop r6


    【解决方案1】:

    我不知道 R6 中用于归档这些任务的内置函数。

    但是,有一种方法可以通过使用具有引用语义的成员来自己编写类似的功能。这样做的原因是引用成员将在类的所有实例之间共享,如here 所述

    如果您的 R6 类包含任何也具有引用语义的字段(例如,其他 R6 对象和环境),则应在初始化方法中填充这些字段。如果该字段直接在类定义中设置为引用对象,则该对象将在 R6 对象的所有实例之间共享。

    在下文中,我将只介绍 B. 和 C.,因为 A. 已经回答了 here(如问题中所述)。

    基本设置

    您必须“直接在类定义中”添加具有引用语义的成员,并在创建新实例时更改该成员。

    library(R6)
    
    foo <- R6Class(
      public = list(
        info = new.env(),                        # member with reference semantics
        initialize = function(ID){
          self$info$IDs = c(self$info$IDs, ID)   # "push_back" new ID
        }
      )
    )
    
    a_name <- foo$new("a_id")
    b_name <- foo$new("b_id")
    
    a_name$info$IDs
    # [1] "a_id" "b_id"
    b_name$info$IDs
    # [1] "a_id" "b_id"
    

    请注意,此代码将为您提供实例 IDs 而不是实例 names

    继承

    通过从父类(又名super 类)调用 ID 管理器来继承此行为非常简单。

    bar <- R6Class(
      inherit = foo,
      public = list(
        initialize = function(ID){
          super$initialize(ID)        # use ID management from the super class
        }
      )
    )
    
    c_name <- bar$new("c_id")
    c_name$info$IDs
    # [1] "a_id" "b_id" "c_id"
    

    列表IDs 现在将包含foobar 实例的所有ID。

    一个不错的包装器

    如果您想从 foo 对象而不是它的实例中获取 ID,可以使用以下方法

    # add a new "static" function to the R6Class/environment foo
    foo$getIDs <- function(){
      dummy_instance <- foo$new(NULL)  # inserting NULL in an unnamed list does nothing
      dummy_instance$info$IDs
    }
    
    foo$getIDs()
    # [1] "a_id" "b_id" "c_id"
    

    我知道这不是您要求的,因为此应用程序会为您提供 ID 而不是名称,但对于某些目的而言,这可能就足够了。

    【讨论】:

      【解决方案2】:

      我认为这个辅助函数可以满足您的需求:

      findR6_obj <- function(className=NULL){
          classList <- eapply(.GlobalEnv, class)
          obj_R6 <- classList[vapply(classList, function(ele) "R6" %in% unlist(ele), logical(1))]
          if (is.null(className)) {
              return(obj_R6)
          } else {
              names(obj_R6[vapply(obj_R6, function(ele) className %in% unlist(ele), logical(1))])
          }
      }
      

      如果你在没有参数的情况下使用它,它将返回全局环境中的所有 R6 对象(以及关于它们的类的更多信息),如果你将它与 className 的参数一起使用,比如 Foo ,它将返回那些包含Foo 的R6 类。

      您可以对其进行修改,使其仅在某些特定环境中显示。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-05-26
        • 1970-01-01
        • 2012-08-27
        • 2020-10-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多