In a package, I have a function foo
that returns an object of class "foo"
. I also have a plot
method for class "foo"
.
#' Create a "foo" object
#'
#' @param x An \R object.
#'
#' @return
#' A "foo" object.
#'
#' @examples
#' foo_object <- foo(1)
#' plot.foo(foo_object)
#'
#' @export
foo <- function(x) {
structure(x, class = "foo")
}
#' @export
#' @importFrom graphics plot
plot.foo <- function(x, ...) {
class(x) <- setdiff(class(x), "foo")
plot(x)
invisible(NULL)
}
I can evaluate the example code without issue after I load the package with devtools::load_all
. However, devtools::check
complains:
Error in plot.foo(foo_out) : could not find function "plot.foo"
Execution halted
It seems that my R session knows about plot.foo
, but not devtools::check
. What is going on?
Edit: To clarify, devtools::check
passes when I replace the call plot.foo(foo_object)
under @examples
with plot(foo_object)
. That doesn't surprise me, and users should call the generic anyway. My question remains: why is devtools::check
unable to find plot.foo
, given that I have used the @export
tag and S3method(plot, foo)
appears in NAMESPACE
after devtools::document
?
If you want to be able to call plot.foo
directly, then you will need to explicitly export that version as well. By convention, usually you do not export class-specific implemenations of generic functions from your package. Normally you just declare that the S3 method exists and leave the function unexported. Like if you call methods(plot)
you'll see a bunch with asterisks which means they are unexpected and are not meant to be called directly. If you do for some reason want to export it as a separate function, you can add an additional export statement. For example
#' @rdname foo-methods
#' @export plot.foo
#' @export
#' @importFrom graphics plot
plot.foo <- function(x, ...) {
class(x) <- setdiff(class(x), "foo")
plot(x)
invisible(NULL)
}