R's documentation is somewhat confusing as to whether @
is already a generic or not: the help page for @
says it is, but it isn't listed on the internalGenerics
page.
The @
operator has specific behaviour as well as (perhaps) being a generic. From the help page for @
: "It is checked that object is an S4 object (see isS4), and it is an error to attempt to use @ on any other object." That would appear to rule out writing methods for S3 classes, though the documentation is unclear if this check happens before method dispatch (if there is any) or after (whence it could be skipped if you supplied a specific method for some S3 class).
You can implement what you want by completely redefining what @
is, along the line of the suggestion in comments:
`@.default` <- function(e1,e2) slot(e1,substitute(e2))
but there are two reasons not to do this:
1) As soon as someone loads your package, it supersedes the normal @
function, so if people call it with other S4 objects, they are getting your version rather than the R base version.
2) This version is considerably less efficient than the internal one, and because of (1) you have just forced your users to use it (unless they use the cumbersome construction base::"@"(e1,e2)
). Efficiency may not matter to your use case, but it may matter to your users' other code that uses S4.
Practically, a reasonable compromise might be to define your own binary operator %@%
, and have the default method call @
. That is,
`%@%` <- function(e1,e2) slot(e1,substitute(e2))
setGeneric("%@%")
This is called in practice as follows:
> setClass("testClass",slots=c(a="character")) -> testClass
> x <- testClass(a="cheese")
> x %@% a
[1] "cheese"