2

我正在开发一个 R 包并在内部使用 R6。我有两个 R6 对象:

  1. Foo包含大量数据的对象和汇总整个数据的方法;
  2. 一个Bar对象,其中包含Foo的数据的子集方法和查询特定子集数据的方法。

我想要做的是创建Bar R6Class Generator对象的克隆并传递一个包含Foo对象所有数据的环境。我找不到完成克隆R6Class Generator.

注意:我不想直接拆分数据Foo并将数据传递给Bar$new,这将大大减慢整个过程,因为Bar将创建大量对象而不是唯一需要的对象。

下面是一个简单的例子:

library(R6)

Foo <- R6Class(classname = "Foo",
    public = list(
        initialize = function (x) {
            private$m_x <- x
            private$m_bar_gen <- private$create_bar_gen(Bar)
        },

        new_bar = function () {
            private$m_bar_gen$new()
        }),

    private = list(
        m_x = NULL,
        m_bar_gen = NULL,

        create_bar_gen = function (Bar) {
            my_bar <- list2env(as.list.environment(Bar), parent = emptyenv())
            class(my_bar) <- "R6Generator"
            my_bar$self <- my_bar
            my_bar$set("private", "m_x", private$m_x, overwrite = TRUE)
            my_bar
        }
    )
)

Bar <- R6Class(classname = "Bar",
    public = list(
        initialize = function () {
            stopifnot(!is.null(private$m_x))
            private$m_x
        }
    ),
    private = list(
        m_x = NULL
    )
)

这将停止,因为private$m_x未定义

Bar$new()
#> Error: !is.null(private$m_x) is not TRUE

Foo对象初始化后,

(foo_1 <- Foo$new(1))
#> <Foo>
#>   Public:
#>     clone: function (deep = FALSE) 
#>     initialize: function (x) 
#>     new_bar: function () 
#>   Private:
#>     create_bar_gen: function (Bar) 
#>     m_bar_gen: R6Generator
#>     m_x: 1

这会起作用

foo_1$new_bar()
#> <Bar>
#>   Public:
#>     clone: function (deep = FALSE) 
#>     initialize: function () 
#>   Private:
#>     m_x: 1

但原来的BarR6Class 生成器也已更改

Bar$private_fields$m_x
#> [1] 1

似乎private$create_bar_gen()无法完成复制 R6Class Generator。my_bar$set将同时设置原始和新的。

(foo_2 <- Foo$new(2))
#> <Foo>
#>   Public:
#>     clone: function (deep = FALSE) 
#>     initialize: function (x) 
#>     new_bar: function () 
#>   Private:
#>     create_bar_gen: function (Bar) 
#>     m_bar_gen: R6Generator
#>     m_x: 2

foo_2$new_bar()
#> <Bar>
#>   Public:
#>     clone: function (deep = FALSE) 
#>     initialize: function () 
#>   Private:
#>     m_x: 2

Bar$private_fields$m_x
#> [1] 2

foo_1$new_bar()
#> <Bar>
#>   Public:
#>     clone: function (deep = FALSE) 
#>     initialize: function () 
#>   Private:
#>     m_x: 2
4

0 回答 0