使用 R6,我如何找到 类 和从某些超类继承的对象?

Using R6, how do I find classes and objects that inherit from some superclass?

假设我有:

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

f <- Foo$new()

一个。我可以做类似

的事情吗
R6::findChildren("Foo")
[1] "Bar1" "Bar2"

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

乙。我可以做类似

的事情吗
R6::findInstances("Foo")
[1] "f"

C。我可以做类似

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

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

然而,有一种方法可以通过使用具有引用语义的成员自己编写类似的功能。原因是参考成员将在 class 的所有实例之间共享,如 here

所述

If your R6 class contains any fields that also have reference semantics (e.g., other R6 objects, and environments), those fields should be populated in the initialize method. If the field set to the reference object directly in the class definition, that object will be shared across all instances of the R6 objects.

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

基本设置

您将必须添加一个具有引用语义的成员 "directly in the class definition" 并在创建新实例时更改该成员。

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.

继承

通过从父 class 调用 ID 管理器继承此行为非常简单(a.k.a。super class)。

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 而不是名字,但对于某些目的来说这可能就足够了。

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

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))])
    }
}

如果您不带参数使用它,它将 return 全局环境中的所有 R6 对象(以及有关它们的更多信息 class),如果您使用它className 的参数,比如 Foo,它将 return 那些包含 Foo 的 R6 classes。

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