R6类,获取所有字段作为命名列表

问题描述

我想以列表的形式检索我的R6Class对象的所有属性的值。优选地,值将带有属性名称。理想情况下,可以将其写成一般形式,以便它也适用于继承的类。不幸的是R6文档不够全面,我找不到类似的问题。

以下基本示例应演示我目前拥有的产品以及目标解决方案的外观。

Person <- R6::R6Class("Person",public = list(
  age = NULL,gender = NULL,initialize = function(age,gender = "M") {
    self$age <- age
    self$gender <- gender
  },list_attributes = function(){
    return(list(self$age,self$gender))
  }
))

p <- Person$new(age=42,gender="W")
p$list_attributes()

# Output
> [[1]]
> [1] 42

> [[2]]
> [1] "W"

list_attributes部分地满足了我的要求,但是我认为应该有一种比明确命名所有公共属性更好的方法获取所有公共属性。我发现使用str(p)可以获取有关对象的一些信息,但不是我想要的形式。

> str(p)
Classes 'Person','R6' <Person>
  Public:
    age: 42
    clone: function (deep = FALSE) 
    gender: W
    initialize: function (age,gender = "M") 
    list_attributes: function () 

我想要的输出口是:

list(age=42,gender="M")
$age
[1] 42

$gender
[1] "M"

有人知道如何实现吗?

解决方法

R6::Class打印功能的source code帮助我更加接近了所需的解决方案。

Person <- R6::R6Class("Person",private = list(
    class = Person
  ),public = list(
    age = NULL,gender = NULL,initialize = function(age,gender = "M") {
      self$age <- age
      self$gender <- gender
    },public_fields = function(){
      return(names(private$class$public_fields))
    },list_attributes = function(){
    
    values <- purrr::map(self$public_fields(),~.subset2(self,.x))
    names(values) <- self$public_fields()
    
    return(values)
  }
))

现在该函数产生所需的输出,但是我必须指定我现在做的类作为私有成员变量。如果可以动态地做到这一点,我会很高兴。

现在的输出是:

> p <- Person$new(age=42,gender="W")
> p$list_attributes()
$age
[1] 42

$gender
[1] "W"
,

感谢您的提问和回答,我一直在努力解决同一问题。

此问题与我最近问过的有关更改对象here中的self类别的问题有关。

正如我所解释的那样,可以使用class(self)访问对象内的对象类,因此不需要使用私有的“类”字段,因此可以使用您的对象结构为:

Person <- R6::R6Class("Person",public = list(
                        age = NULL,gender = "M") {
                          self$age <- age
                          self$gender <- gender
                        },public_fields = function(){
                          return(names(get(class(self))$public_fields))
                        },list_attributes = function(){
                          
                          values <- purrr::map(self$public_fields(),.x))
                          names(values) <- self$public_fields()
                          
                          return(values)
                        }
                      ))

哪个给:

> p <- Person$new(age=42,gender="W")
> p$public_fields()
[1] "age"    "gender"
> p$list_attributes()
$age
[1] 42

$gender
[1] "W"

,只需将它们全部放在一个active字段中,然后使用set_names()

Person <- R6::R6Class("Person",gender = "M") {
                          self$age <- age
                          self$gender <- gender
                        }
                        ),active = list(
                        
                        my_fields = function(){
                          purrr::map(names(get(class(self))$public_fields),.x)) %>% 
                            set_names(names(get(class(self))$public_fields))
                        }
                      ))

哪个给:

> p <- Person$new(age=42,gender="W")
> p$my_fields
$age
[1] 42

$gender
[1] "W"