Actual question
How can I turn a bunch of R6 classes that inherit from each other into S4 classes while preserving the inheritance structure when all classes need to live in a package's namespace (as opposed to in GlobalEnv)?
Details
Everything works fine in cases where the R6 classes have been defined in .GlobalEnv (as when sourcing with source()) and setOldClass() is also called with where = .GlobalEnv.
But I cannot get it to work when the R6 classes have been defined inside a package's namespace (as when calling devtools::load_all()):
Defining the R6 classes in .GlobalEnv:
Object <- R6Class("Object", portable = TRUE, public = list(
foo = function() "foo")
)
Api <- R6Class("Api", inherit = Object, portable = TRUE,
public = list(bar = function() "bar")
)
Module <- R6Class("Module", inherit = Api, portable = TRUE,
public = list(fooBar = function() "fooBar")
Calling setOldClass() with where = .GlobalEnv (the default for where):
setOldClass(c("Object", "R6"))
setOldClass(c("Api", "Object"))
setOldClass(c("Module", "Api"))
When the R6 classes are defined inside a package's namespace (as when "sourcing" with devtools::load_all() instead of source()), I assumed that I need to account for that by providing an explicit where:
where <- if ("package:r6.s4" %in% search()) {
as.environment("package:r6.s4")
} else {
.GlobalEnv
}
try(setOldClass(c("Object", "R6"), where = where))
try(setOldClass(c("Api", "Object"), where = where))
try(setOldClass(c("Module", "Api"), where = where))
However, that leaves me with the following error:
Error in setOldClass(c("Module", "Api"), where = where) : inconsistent old-style class information for “Module”; the class is defined but does not extend “Api” and is not valid as the data part
Facilitating reproducability
I tried to make this issue as easily reproducible as possible, so you'll find the r6.s4 package at my GitHub repository
Note again that you have to run devtools::load_all() (or hit CRTL + SHFT + L in RStudio) in order to reproduce the error.
Also, this unit test might help in figuring out what's going on.