3

我正在编写一个包含多个方法的 R6 类的包。我希望能够为类和方法生成文档。对于下面的示例,我希望能够使用?Person类和?set_hair方法访问文档。这是我的示例类:

#' This is my Person class
#' @title Person Class
#' @docType class
#' @description Person class description
#' @field name Name of the person
#' @field hair Hair colour
#'
#' @section Methods:
#' \describe{
#' \item{set_hair Set the hair color}
#' }
#' 
#' @examples
#' Person$new(name="Bill", hair="Blond")
#' @export
Person <- R6::R6Class("Person",
  public = list(
    name = NULL,
    hair = NULL,
    initialize = function(name = NA, hair = NA) {
      self$name <- name
      self$hair <- hair
  },    

    # '@name set_hair
    # '@param val: hair colour
    set_hair = function(val) {
      self$hair <- val
  },
  )
)

运行roxygenise()时,方法体上方的注释根本不会呈现,所以我指定的唯一信息@section Methods是在文档中。

由于我有超过 50 个类方法,如果我可以单独访问方法文档会更好?methodname。我发现了一些关于此的帖子(在 RStudio 的 R 包中记录 R6 类和方法https://github.com/klutometis/roxygen/issues/306),但在我看来,这不支持 R6 类。

分别记录我的类方法的最佳方法是什么?

4

2 回答 2

2

这是一篇旧帖子,您可能很久以前就解决了您的问题。但它没有在这里添加,所以如果有人需要解决方案,它将是:

#' This is my Person class
#' @description Person class description
#' @field name Name of the person
#' @field hair Hair colour
#' 
#' @examples
#' Person$new(name="Bill", hair="Blond")
#' @export
Person <- R6::R6Class("Person",
  public = list(
    name = NULL,
    hair = NULL,

    #' @description
    #' Create a person
    #' @param name Name of the person
    #' @param hair Hair colour
    initialize = function(name = NA, hair = NA) {
      self$name <- name
      self$hair <- hair
  },    

    #' @description Set hair
    #' @param val Hair colour
    set_hair = function(val) {
      self$hair <- val
  },
  )
)
于 2021-07-24T12:07:53.973 回答
2

上面 user2554330 的评论中链接的关于 github 提出的问题的讨论表明,分离出的文档不在 roxygen 的待办事项清单上,因为它不符合方法文档的传统风格。也就是说,我仍然发现它很有用,并且一直在使用一种解决方法。

一种部分解决方案是创建功能包装器。这是一个半手动过程,给定许多方法(如您的情况)可能会很麻烦,但它确实在单独的文档中为 R6 方法启用了清晰和半自动化的文档。使用该person示例,这是 roxygen2 中可文档化包装器的可能实现:

#` Method for setting hair
#` 
#` @param person a person class object
#` @param val hair color
#` 
#` @return nothing; modifies \code{person}
#` @export
#` 
#` @examples
#` bill <- Person$new(name="Bill", hair="Blond")
#` bill$set_hair("InspiredRed")
#` bill$hair
#` set_hair(bill, "MetalBlack")
#` bill$hair
set_hair <- function(person, val){
  person$set_hair(val)
  invisible()
}

结果将是两个单独.Rd的文件,一个用于person类,一个用于set_hair方法,都可以使用?.

结果有一个额外的优势,大多数 R 用户可能更喜欢更接近函数形式的调用,因为这更接近大多数 R 语法的设置方式。两者person$set_hair(val)set_hair(person, val)都将产生相同的结果,无需任何显式分配,保持 R6 的优势,同时增加最小的开销。


编辑:

在向一些人提出这个问题后,我发现更喜欢使用实际的函数式表单包装器——那些牺牲参考组件以支持函数式方法的封装器,因为它更接近 R 的“规范”。在这种情况下,该方法仍然提供相同的文档优势,而引用方法调用仍然可以通过$. 但是,在编写包装文档时,应额外强调引用方法方法的存在。

#` Clones person and changes hair
#` 
#` @param person a person class object
#` @param val hair color
#` 
#` @return nothing; modifies \code{person}
#` @export
#` 
#` @details This creates a new person with the same characteristics as the \code{person}
#' provided, except with new hair. To update the original person's hair by reference,
#' use \code{person$set_hair()}.
#` 
#` @examples
#` bill <- Person$new(name="Bill", hair="Blond")
#` bill$set_hair("InspiredRed")
#` bill$hair
#` set_hair(bill, "MetalBlack")
#` bill$hair
set_hair <- function(person, val){
  personNew <- person.clone()
  personNew$set_hair(val)
  invisible(personNew) # invisible assuming no print method, but you probably want one
}

当然,使用这些包装器采用哪种方式取决于您特定应用程序的速度和内存要求。功能性方法可能会造成足够多的障碍,使其不可行。

于 2018-05-30T15:36:41.590 回答