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

如何让R的R6类initialize方法从create_person继承Roxygen2参数?

R6类initialize方法参数注释继承失败的解决办法

问题重现

我定义了Person R6类,同时写了包装Person$new()的create_person()函数,两者参数完全一致。想让Person$initialize的参数注释从create_person继承,但执行devtools::document()时触发如下报错:

devtools::document()
#> ✖ Person.R:5: Must use one @param for each argument.
#> ✖ $initialize(name) is not documented
#> ✖ Person.R:5: Must use one @param for each argument.
#> ✖ $initialize(age) is not documented
#> ✖ In topic 'Chat': @inheritParams failed.
#> ℹ All parameters are already documented; none remain to be inherited.
#> ✖ In topic 'Person': @inheritParams failed.
#> ℹ All parameters are already documented; none remain to be inherited.

已尝试的无效方案

  1. 反向继承:在Person$initialize中写参数注释,让create_person继承,无效。
  2. 自定义函数提取参数注释:分别尝试从R源码文件和生成的man文件提取注释插入Roxygen,均失败。相关代码如下:
    • 从R文件提取参数的函数:
      inherit_params <- function(file, func) {
        x <- readLines(file)
        is_func <- startsWith(trimws(x), func)
        x_before <- x[cumsum(is_func) == 0]
        is_not_comment_rev <- !startsWith(rev(x_before), "#'")
        lines_with_comment <- rev(rev(x_before)[cumsum(is_not_comment_rev) == 0])
        params <- lines_with_comment[grepl("@param", lines_with_comment)]
        paste(gsub("#' ", "", c(params, "\n")), collapse = "\n")
      }
      
      对应的Roxygen注释片段:
      #' @description Initialize a Person Object (Class Init)
          #' `r inherit_params("R/Person.R", "create_person")`
          initialize = function(name, age) {
      
    • 从man文件提取参数的函数:
      inherit_params_man <- function(func) {
        x <- readLines(sprintf("man/%s.Rd", func))
        is_args <- which(startsWith(trimws(x), "\\arguments{"))
        is_closing <- which(startsWith(trimws(x), "}"))
        diff <- is_closing - is_args
        diff <- diff[diff > 0]
        nlines <- min(diff)
        x[is_args:(is_args + nlines)]
      }
      
      对应的Roxygen注释片段:
      #' @description Initialize a Person Object (Class Init)
          #' `r inherit_params_man("create_person")`
          initialize = function(name, age) {
      

原代码

Person类与create_person函数

#' Person example class, where the initialize parameters should be inherited from create_person
#'
#' @export
#' @inherit create_person return examples
Person <- R6::R6Class(
  "Person",
  public = list(
    #' @field name The name of the person
    name = NULL,

    #' @field age The age of the person
    age = NULL,

    #' @description Initialize a Person Object
    #' @inheritParams create_person
    initialize = function(name, age) {
      self$name <- name
      self$age <- age
    }
  )
)

#' Creates a new Person
#'
#' @param name name of the person
#' @param age age of the person
#'
#' @return a new Person object
#' @export
#'
#' @examples
#' create_person("John", 30)
create_person <- function(name, age) {
  Person$new(name, age)
}

原因分析

Roxygen的@inheritParams机制对R6类方法的支持有限:R6类的文档主题和普通函数的文档主题是分离的,直接在initialize方法的注释中引用普通函数的参数注释会被Roxygen识别为无效操作,因为它无法跨主题继承参数描述。

解决方案

方案1:反向继承(推荐)

让create_person继承Person类的参数注释(更合理,因为类的初始化方法是参数的源头),具体代码如下:

#' Person example class
#'
#' @export
#' @return a new Person object
#' @examples
#' Person$new("John", 30)
Person <- R6::R6Class(
  "Person",
  public = list(
    #' @field name The name of the person
    name = NULL,

    #' @field age The age of the person
    age = NULL,

    #' @description Initialize a Person Object
    #' @param name name of the person
    #' @param age age of the person
    initialize = function(name, age) {
      self$name <- name
      self$age <- age
    }
  )
)

#' Creates a new Person
#'
#' @export
#' @inheritParams Person
#' @inherit Person return examples
create_person <- function(name, age) {
  Person$new(name, age)
}

执行devtools::document()即可正常生成文档,参数注释会从Person类的initialize方法继承到create_person函数,同时Person类的初始化参数也有明确的注释。

方案2:类主注释继承参数

如果坚持要让Person类继承create_person的参数注释,可以在类的主注释中添加@inheritParams create_person,并在initialize方法中保留空的@param标签:

#' Person example class
#'
#' @export
#' @inherit create_person return examples
#' @inheritParams create_person
Person <- R6::R6Class(
  "Person",
  public = list(
    #' @field name The name of the person
    name = NULL,

    #' @field age The age of the person
    age = NULL,

    #' @description Initialize a Person Object
    #' @param name 
    #' @param age 
    initialize = function(name, age) {
      self$name <- name
      self$age <- age
    }
  )
)

#' Creates a new Person
#'
#' @param name name of the person
#' @param age age of the person
#'
#' @return a new Person object
#' @export
#'
#' @examples
#' create_person("John", 30)
create_person <- function(name, age) {
  Person$new(name, age)
}

这样Roxygen会将类主注释中的参数描述关联到initialize方法的参数上,避免报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 11:54:54