【问题标题】:Access elements of an R6 class that instantiates another R6 class访问实例化另一个 R6 类的 R6 类的元素
【发布时间】:2020-09-01 19:53:08
【问题描述】:

假设我有一个类 SimpleClass 并且该类的方法之一可以返回另一个类的对象,例如

SimpleClass <- R6::R6Class(
  "SimpleClass",
  public = list(
    initialize = function() {
      private$a <- 1
    },
    cls_two = function() SimpleClass2$new()
  ),
  private = list(
    a = numeric()
  )
)

SimpleClass2 在哪里

SimpleClass2 <- R6::R6Class(
  "SimpleClass2",
  public = list(
    initialize = function() {
      private$b <- 2
    },
    get_a = function() private$a
  ),
  private = list(
    b = numeric()
  )
)

在这里,如果我实例化 SimpleClass 并调用方法 cls_two(),则生成的对象将无法访问第一个对象的元素,除非我传递它们。二级类有没有办法访问一级类的元素?

first <- SimpleClass$new()
second <- first$cls_two()
second$get_a()
# NULL

请注意,我不想使用传统意义上的继承,因为我不想重新实例化第一个类。我也希望不必将所有对象都传递给SimpleClass2$new()

【问题讨论】:

  • 我最近遇到了类似的问题,通过共享环境解决了。基本上在 SimpleClass init 方法中创建一个环境并将该环境传递给类 SimpleClass2 的第二个对象。另一个选项是将 SimpleClass“self”直接传递给您使用 SimpleClass2$new() 实例化的对象。如果您需要示例,请告诉我,我可以创建它。
  • 是的,这不是一个坏主意。我已经考虑过包内的共享环境,但是在类内是个好主意!如果 R6 没有内置的方法来做到这一点,我会感到惊讶。

标签: r r6


【解决方案1】:

扩展SimpleClass2的构造函数以获取SimpleClass类型的对象,并在SimpleClass::cls_two中调用构造函数时传递self

SimpleClass2 <- R6::R6Class(
  "SimpleClass2",
  public = list(
    initialize = function(obj) {
      private$b <- 2
      private$obj <- obj
    },
    get_a = function() private$obj
  ),
  private = list(
    b = numeric(),
    obj = NULL
  )
)

【讨论】:

  • 这不是同一个答案吗?不过我想它更整洁。如果 NULL 就足够了,不要创建不必要的 R6 对象。
  • @AllanCameron 是的,几乎一样。当我提交答案时,还没有答案——我实际上已经写好了,只是想试试,然后回来按“提交”。
  • 那么除了传递 self 和/或 private 之外没有别的方法吗?因为我可能希望能够使用不同的参数分别实例化 SimpleClass2。很遗憾,我必须明确地传递 self 而我不能直接访问它。
  • @nathaneastwood 您可以分别实例化 SimpleClass2,只需为 obj 设置一个默认 NULL,以便仅由 SimpleClass 中的构造函数使用。从构造函数传递self 有什么问题?无论如何,您都是通过引用传递的,所以这是一个非常便宜的副本。此外,它提供的界面与您在示例中想要的界面相同。
  • 对我来说,默认情况下为 NULL 的参数不会对用户非常友好,并且只有在被另一个类调用时才需要。我可能需要多考虑一下我的界面。
【解决方案2】:

你可以让 SimpleClass2 有一个 Simpleclass 的成员,并且可以选择在它的构造函数中传递一个 simpleclass:

SimpleClass <- R6::R6Class(
  "SimpleClass",
  public = list(
    initialize = function() {
      private$a <- 1
    },
    cls_two = function() SimpleClass2$new(self)
  ),
  private = list(
    a = numeric()
  )
)

SimpleClass2 <- R6::R6Class(
  "SimpleClass2",
  public = list(
    initialize = function(Simp1 = SimpleClass$new()) {
      private$a <- Simp1
      private$b <- 2
    },
    get_a = function() private$a
  ),
  private = list(
    a = SimpleClass$new(),
    b = numeric()
  )
)

像这样工作:

first <- SimpleClass$new()
second <- first$cls_two()
second$get_a()
#> <SimpleClass>
#>   Public:
#>     clone: function (deep = FALSE) 
#>     cls_two: function () 
#>     initialize: function () 
#>   Private:
#>     a: 1

【讨论】:

    猜你喜欢
    • 2022-08-04
    • 2015-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多