如何使用Roxygen正确记录来自不同包的通用S3方法?

49
我正在编写一个新类surveyor,其中定义了一个print方法print.surveyor的包。我的代码可以正常工作,并且我使用Roxygen进行内联文档记录。但是,命令R CMD check会发出警告:

在文档对象'print.surveyor'中具有用法但未在代码中出现的函数/方法:print

以下两个页面均由Hadley编写,对我有所启发:NamespacesDocumenting functions,两者都指出正确的语法是@method function-name class

因此,我的问题是:如何使用Roxygen正确记录我的新类的print方法?更具体地说,如何消除警告?


这是我的代码:(注释的文档记录指出了尝试修复此问题的方法,但没有起作用。)

#' Prints surveyor object.
#' 
#' Prints surveyor object
#' 
## #' @usage print(x, ...)
## #' @aliases print print.surveyor
#' @param x surveyor object
#' @param ... ignored
#' @S3method print surveyor
print.surveyor <- function(x, ...){
    cat("Surveyor\n\n")
    print.listof(x)
}

以下是经过Roxygen处理后的输出结果,即print.surveyor.Rd

\name{print.surveyor}
\title{Prints surveyor object.}
\usage{print(x, ...)
#'}
\description{Prints surveyor object.}
\details{Prints surveyor object

#'}
\alias{print}
\alias{print.surveyor}
\arguments{\item{x}{surveyor object}
\item{...}{ignored}}
3个回答

44

更新

从roxygen2 > 3.0.0版本开始,该软件包已经变得更加智能,可以为您解决很多问题。现在,您只需要使用@export标签,roxygen将根据您所记录的内容自动判断应该如何编写NAMESPACE等文件。

当然,也有一些例外情况需要您手动帮助roxygen。比如,Hadley Wickham在他的《R Packages》书中提到的一个example函数all.equal.data.frame。这个函数名存在歧义,不清楚哪部分是类(class),哪部分是通用函数(generic function)(all, all.equal还是all.equal.data)?

在这种情况下,您可以通过明确地告诉roxygen哪部分是通用函数,哪部分是类/方法来帮助它进行判断,例如:

@method all.equal data.frame

下面的原始答案更多地解释了旧有行为,如果需要显式使用@method,请参考下文。

原始内容

应使用@method标签记录函数文档:

#' @method print surveyor

在初次阅读@hadley的文档时,因为我不熟悉roxygen,所以有些困惑,但经过多次阅读该部分后,我认为我理解了为什么需要使用@method。
您正在编写print方法的完整文档。 @S3methodNAMESPACE相关,并安排导出方法@S3method不适用于记录方法。
您的Rd文件应在usage部分包含以下内容:
\method{print}{surveyor}(x, ...)

如果这个正确地工作,那就是在Rd文件中记录S3方法的正确方式。

1
@Backlin 那有什么问题吗?这看起来像是在Rd中标记和S3方法的正确方式。它将以正确的方式呈现在使用部分,但在使用代码上方会有## S3 method blah blah - Gavin Simpson
非常好的回答。那么@S3method是怎么回事呢?我应该同时使用它们吗?对于S3方法,@S3method是否与@export相同? - cboettig
@cboettig 不,它们非常不同。@S3method 注册方法但不导出它,因此可以从 foo() 调用它,但不能通过 foo.bar() 显式调用它。如果您还要 @export 该方法,则可以直接调用它。通常情况下,您不希望导出方法,只需注册它们,但在某些情况下,您可能需要导出方法,在这些情况下,您需要同时使用 @S3method@export - Gavin Simpson
@GavinSimpson 谢谢!通常我需要同时使用 @method@S3method,但不需要 @export 吗? - cboettig
3
是的,@method是文档(.Rd文件)的标签,而@S3method是命名空间机制的标签。如果你有自己的NAMESPACE文件,现在这两个都需要。只有当你真的想要使方法在包的命名空间之外可见时,才需要使用@export标签。 - Gavin Simpson
显示剩余3条评论

29

从roxygen2 > 3.0.0版本开始, 您只需要使用@export标记,因为roxygen可以确定print.surveyor是一个S3方法。这意味着您现在只需要:

#' Prints surveyor object.
#' 
#' @param x surveyor object
#' @param ... ignored
#' @export
print.surveyor <- function(x, ...){
    cat("Surveyor\n\n")
    print.listof(x)
}

不过,在这种情况下,由于文档不是很有用,最好只做如下操作:

#' @export
print.surveyor <- function(x, ...){
    cat("Surveyor\n\n")
    print.listof(x)
}

好的。谢谢。我会立即尝试! - Andrie
1
嗯,我想注册一个不导出的S3方法。不幸的是,这会生成一个弃用警告。有没有什么解决办法? - Konrad Rudolph
@KonradRudolph,注册S3方法而不导出它是什么意思? - hadley
1
@hadley 我想避免使用 @export,因为这样 R CMD check 就会抱怨未记录的参数(我没有记录该方法,因为它本来就应该是不可见的)。然而,现在我无法重现这个问题:没有生成 .Rd 文件,也没有显示任何 R CMD check 警告缺少参数。我可能之前在文档注释中有一些空行,导致为此方法生成了不完整的文档。 - Konrad Rudolph

3

@export 只在泛型类被加载时起作用。如果泛型类在另一个包中,则需要导入该泛型类。在当前的 Roxygen 中,可以通过以下方式解决此问题:

#' @importFrom tibble data_frame
#' @export
tibble::data_frame

选自 dplyr/R/reexport-tibble.r 。在这个例子中,data_frame 方法被从tibble包导入,并且tibble::data_frame被导出。这样重新导出的对象将会被记录在reexports.Rd文件中,而这个文件可以通过R CMD check来满足要求。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接