You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决R包中使用内部数据的R6Class出现对象未找到错误?

问题:R包中R6对象引用内部变量触发“对象未找到”错误

我按照Konrad Rudolph的建议将sysdata.R移至data-raw文件夹并重命名为DATASET.R,但问题根源不在此,而是由problem_R6.R中定义的R6对象导致的。

我正在学习R6,尝试创建一个简单的R6类,使其使用data-raw/DATASET.R生成的内部变量。示例包基于默认R包模板,仅包含三个自定义R文件:

1. data-raw/DATASET.R(生成内部变量)

internal_name  <- "Eric"

usethis::use_data(internal_name, internal = TRUE, overwrite = TRUE)

2. R/R6_Class_1.R(定义基础R6类)

#' @import R6
#'
#' @noRd

name <- R6::R6Class(
  classname = "name",
  private = list( target_name = NULL),
  public = list(
    initialize = \(text) { private$target_name <- text },
    get_name = \() { private$target_name }
  )
)

3. R/problem_R6.R(定义问候类,触发错误)

#' @import R6
#'
#' @noRd

greeting <- R6::R6Class(
  classname = "greeting",
  private = list(
    name = name$new(text = internal_name)
  ),
  public = list(
    message = NULL,
    initialize = \() { self$message = "Hello! " },
    greet = \() { paste0(self$message, private$name$get_name(), "!") }
  )
)

错误信息

清理并安装包时,收到如下错误:

Error in eval(exprs[i], envir) : object 'internal_name' not found
Error: unable to load R code in package 'testingR6'
Execution halted
ERROR: lazy loading failed for package 'testingR6'
* removing 'C:/Users/.../R/win-library/4.4/testingR6'
* restoring previous 'C:/Users/H.../R/win-library/4.4/testingR6'

Exited with status 1.

包结构

> fs::dir_tree()
.
├── data-raw
│   └── DATASET.R
├── DESCRIPTION
├── man
├── NAMESPACE
├── R
│   ├── problem_R6.R
│   ├── R6 Class 1.R
│   └── sysdata.rda
└── testingR6.Rproj

我确认sysdata.rda由DATASET.R生成,加载时internal_name确实存在,但不清楚报错原因,想知道如何修复让包能正常包含该R6对象。


解决方案

问题根源

R包加载时会先解析执行R/目录下的所有脚本,之后才会加载sysdata.rda中的内部变量。你原来的代码在定义R6类的阶段就直接执行了name$new(text = internal_name),此时internal_name还未被加载到包的命名空间中,因此触发“对象未找到”错误。

修改代码

将private$name的初始化逻辑从类定义阶段移到initialize方法中,确保在创建类实例时,内部变量已经加载完成:

修改后的R/problem_R6.R代码:

#' @import R6
#'
#' @noRd

greeting <- R6::R6Class(
  classname = "greeting",
  private = list(
    name = NULL  # 先初始化为NULL,延迟初始化
  ),
  public = list(
    message = NULL,
    initialize = \() {
      self$message = "Hello! "
      private$name = name$new(text = internal_name)  # 在实例初始化时创建name对象
    },
    greet = \() {
      paste0(self$message, private$name$get_name(), "!")
    }
  )
)

验证

重新清理并安装包,此时创建greeting实例时就能正常访问internal_name,调用greet()方法会输出Hello! Eric!。


内容的提问来源于stack exchange,提问作者Grasshopper_NZ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 12:03:25