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

R6 classes, get all fields as named list

我想以列表的形式检索 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 部分完成了我想要的,但我认为应该有比显式命名所有属性更好的方法来获取所有 public 属性。我发现使用 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)
  }
))

现在该函数产生了所需的输出,但我必须将我现在所做的 class 指定为私有成员变量。如果这可以动态完成,我会很高兴。

现在的输出是:

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

$gender
[1] "W"

感谢您的提问和回答,我也在为同样的问题苦苦挣扎。

这个问题链接到我最近提出的关于更改对象中 self 的 class 的问题,

正如向我解释的那样,可以使用 class(self) 访问对象中的对象 class,因此无需使用私有“class”字段,所以你的问题可以使用你的对象结构来解决:

Person <- R6::R6Class("Person",                     
                      
                      public = list(
                        age = NULL,
                        gender = NULL,
                        
                        initialize = function(age, 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(), ~.subset2(self, .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",                     
                      
                      public = list(
                        age = NULL,
                        gender = NULL,
                        
                        initialize = function(age, gender = "M") {
                          self$age <- age
                          self$gender <- gender
                        }
                        ),
                      active = list(
                        
                        my_fields = function(){
                          purrr::map(names(get(class(self))$public_fields), ~.subset2(self, .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"