R6类嵌套函数访问self报错,求无需升级R6的解决方案
不升级R6解决嵌套函数无法访问self的问题
你遇到的问题本质是:嵌套在普通list中的函数不属于R6类的方法成员,R6只会给直接定义在public/private等区块内的方法自动注入self对象,普通list里的函数没有这个上下文绑定,所以调用时找不到self。以下是无需升级R6的替代解决方案:
方案一:用R6类层级替代嵌套list
把每个层级的嵌套结构都定义成独立的R6类,初始化时传递主Person实例,保持上下文关联:
library(R6) # 定义底层R6类,接收主Person实例 Level3 <- R6Class("Level3", public = list( person = NULL, method = function() { print(self$person$name) }, initialize = function(person) { self$person = person } ) ) Level2 <- R6Class("Level2", public = list( person = NULL, level3 = NULL, initialize = function(person) { self$person = person self$level3 = Level3$new(person) } ) ) Level1 <- R6Class("Level1", public = list( person = NULL, level2 = NULL, initialize = function(person) { self$person = person self$level2 = Level2$new(person) } ) ) # 主Person类,初始化时创建层级实例 Person <- R6Class("Person", public = list( name = NULL, level1 = NULL, initialize = function(name) { self$name = name self$level1 = Level1$new(self) } ) ) jay = Person$new(name = "Jay") jay$level1$level2$level3$method()
方案二:手动给嵌套函数注入self环境
在Person的initialize方法中,修改嵌套函数的运行环境,手动添加self变量:
library(R6) Person <- R6Class("Person", public = list( name = NULL, level1 = list( level2 = list( level3 = list( method = function() { print(self$name) } ) ) ), initialize = function(name) { self$name = name # 用base R修改函数环境,注入self target_func <- self$level1$level2$level3$method new_env <- new.env(parent = environment(target_func)) new_env$self <- self environment(target_func) <- new_env } ) ) jay = Person$new(name = "Jay") jay$level1$level2$level3$method()
若已安装rlang包,可使用更简洁的环境修改方式:
environment(self$level1$level2$level3$method) <- rlang::env( parent = environment(self$level1$level2$level3$method), self = self )
方案三:在initialize中动态构建嵌套结构
把嵌套的list和函数移到initialize方法中定义,利用闭包特性自动捕获当前的self:
library(R6) Person <- R6Class("Person", public = list( name = NULL, level1 = NULL, initialize = function(name) { self$name = name # 在initialize内部构建嵌套结构,函数自动捕获self上下文 self$level1 <- list( level2 = list( level3 = list( method = function() { print(self$name) } ) ) ) } ) ) jay = Person$new(name = "Jay") jay$level1$level2$level3$method()
内容的提问来源于stack exchange,提问作者irudnyts
相关产品推荐
相关产品推荐

