I'd like to understand the steps R goes through to find the appropriate function when mixing S3 and S4. Here's an example:
set.seed(1)
d <- data.frame(a=rep(c('a', 'b'), each=15),
b=rep(c('x', 'y', 'z'), times=5),
y=rnorm(30))
m <- lme4::lmer(y ~ b + (1|a), data=d)
l <- lsmeans::lsmeans(m, 'b')
multcomp::cld(l)
I don't fully understand what happens when the final line gets executed.
multcomp::cld
prints UseMethod("cld")
, so S3 method dispatch.
isS4(l)
shows that l
is an S4 class object.
It seems that, despite calling an S3 generic, the S3 dispatch system is completely ignored. Creating a function print.lsmobj <- function(obj) print('S3')
(since class(l)
is lsmobj
) and running cld(l)
does not print "S3"
.
showMethods(lsmobj)
or showMethods(ref.grid)
(the super class), do not list anything that resembles a cld
function.
Using debugonce(multcomp::cld)
shows that the function that is called eventually is cld.ref.grid
from lsmeans
.
I was wondering, however, how to realise that cld.ref.grid
will eventually be called without any "tricks" like debugonce
. That is, what are the steps R performs to get to cld.ref.grid
.
In order for S3 methods to be registered, the generic has to be available. Here, I write a simple foo
method for merMod
objects:
> library(lme4)
> foo.merMod = function(object, ...) { "foo" }
> showMethods(class = "merMod")
Function ".DollarNames":
<not an S4 generic function>
Function "complete":
<not an S4 generic function>
Function "formals<-":
<not an S4 generic function>
Function "functions":
<not an S4 generic function>
Function: getL (package lme4)
x="merMod"
Function "prompt":
<not an S4 generic function>
Function: show (package methods)
object="merMod"
> methods(class = "merMod")
[1] anova as.function coef confint cooks.distance
[6] deviance df.residual drop1 extractAIC family
[11] fitted fixef formula getL getME
[16] hatvalues influence isGLMM isLMM isNLMM
[21] isREML logLik model.frame model.matrix ngrps
[26] nobs plot predict print profile
[31] ranef refit refitML rePCA residuals
[36] rstudent show sigma simulate summary
[41] terms update VarCorr vcov weights
Neither list includes foo
. But if we define the generic, then it shows up in methods()
results:
> foo = function(object, ...) UseMethod("foo")
> methods(class = "merMod")
[1] anova as.function coef confint cooks.distance
[6] deviance df.residual drop1 extractAIC family
[11] fitted fixef foo formula getL
[16] getME hatvalues influence isGLMM isLMM
[21] isNLMM isREML logLik model.frame model.matrix
[26] ngrps nobs plot predict print
[31] profile ranef refit refitML rePCA
[36] residuals rstudent show sigma simulate
[41] summary terms update VarCorr vcov
[46] weights
Now it includes foo
Similarly, in your example, methods()
will reveal the existence of cld
if you do library(multcomp)
, because that is where the generic for cld
sits.