3

假设我有:

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"
4

2 回答 2

2

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

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

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

在下文中,我将仅介绍 B. 和 C.,因为 A. 已在此处得到回答(如问题中所述)。

基本设置

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

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"

请注意,此代码将为您提供实例ID而不是实例名称

遗产

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现在将包含foo或的实例的所有 ID bar

一个不错的包装

如果要从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"

我知道这不是你所要求的,因为这个 appriach 会给你 ID 而不是名字,但对于某些目的来说,这可能就足够了。

于 2017-09-17T02:45:43.680 回答
1

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

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,它将返回那些 R6 类包括Foo.

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

于 2019-09-12T07:33:15.937 回答