RConsortium / S7

S7: a new OO system for R
https://rconsortium.github.io/S7
Other
386 stars 32 forks source link

Embedding generics when defining methods #364

Open hadley opened 11 months ago

hadley commented 11 months ago
library(S7)
foo1 <- new_class("foo1", properties = list(x = class_integer))
foo2 <- new_class("foo2", foo1, properties = list(y = class_double))

method(convert, list(foo1, class_integer)) <- function(from, to) {
  from@x
}
ls()
#> [1] "convert" "foo1"    "foo2"

I think this is going to be a problem because defining a method for a generic defined in another package will end up embedding a copy of that generic in your package. Not sure what we can do here given that this is a fairly deep seated behaviour of <- functions.

hadley commented 11 months ago

Oh maybe method<- could just return NULL? — Nope that doesn't work because if the generic is defined in the current environment, it will reset it.

This almost works:

  if (identical(environment(generic), parent.frame())) {
    invisible(generic)
  } else {
    invisible(NULL)
  }

But isn't quite right either.

Maybe we need to do some post-hoc clean up?

hadley commented 10 months ago

Something like this would work:

#' .onLoad <- function(...) {
#'   S7::methods_register()
#' }
#' S7::package_clean_up()
hadley commented 10 months ago

Maybe if generic is an external generic, return that object instead of the actual generic. Do something to these external generic objects on load.

hadley commented 9 months ago

Maybe this isn't as hard as I thought — method_register() already has all the mechanics to return an external generic if needed, and there's no harm in that object continuing to live in the package namespace. (And in fact there's a small advantage in that we only need to create the external generic object once, rather than once each time).