I have a package PackageA
with a generic function:
#' doWork
#'
#' Do some work!
#'
#' @export
setGeneric(
"doWork",
function(x) {
standardGeneric("doWork")
})
setMethod(
"doWork",
signature = c("numeric"),
definition = function(x) {
x == 10 # Some logic...
}
In PackageB
, which depends on PackageA
, I would like to add more methods to doWork
:
#' @import PackageA
setMethod(
"doWork",
signature = c("character"),
definition = function(x) {
length(x) == 1 && x == "10" # Some more logic...
}
This works. However, it means that the user of PackageB
must also library(PackageA)
.
This fails:
library(PackageB)
doWork("10") # Fails!
This works:
library(PackageA)
library(PackageB)
doWork("10")
I would like to use the generic from PackageA
in PackageB
, but not require PackageA
to be loaded to use just the methods in PackageB
.
How can I achieve this?
Generic functions are created and assigned by setGeneric or setGroupGeneric and, indirectly, by setMethod . As you might expect setGeneric and setGroupGeneric create objects of class "genericFunction" and "groupGenericFunction" respectively.
A generic function is one which may be applied to different types of inputs producing results depending on the type of input. Examples are plot() and summary() We demonstrate these differences using sample data from. Dalgaard's Introductory Statistics with R.
This is actually documented, but it's not very clear; see section 1.5.6
of Writing R Extensions.
The trick is to import the generic from PackageA
and then re-export it from PackageB
. Using roxygen
annotations, this looks like:
#' @importMethodsFrom PackageA doWork
#' @export
setMethod(
"doWork",
signature = c("character"),
definition = function(x) {
length(x) == 1 && x == "10" # Some more logic...
})
When you call devtools::document()
, this will fail unless you have first loaded PackageA
(call library(PackageA)
).
However, once built, PackageA
is not required:
> library(PackageB)
> showMethods("doWork")
Function: doWork (package PackageA)
x="character"
x="numeric"
For reference, the auto-generated NAMESPACE
file looks like:
exportMethods(doWork)
importMethodsFrom(PackageA, doWork)
This method produces no warnings about naming conflicts and so on, so it seems to be "kosher".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With