Search code examples
rr-s3

function to return all S3 methods applicable to an object


Has anyone put together/found a good method for listing all the S3 methods available for a given object? The built-in methods() function will give all available methods for a specified class, or for a specified generic function, but not for an object.

The example I have in mind is a glm object, which is of (minor?) class "glm" but also inherits from "lm"

g <- glm(y~x,data=data.frame(x=1:10,y=1:10))
class(g)
## [1] "glm" "lm"

There are 35 methods for class "lm" and 22 for "glm". I'm interested in an answer that combines the results of

lapply(class(g),function(x) methods(class=x))

in a sensible way, so that I can immediately see (for example) that there is a glm-specific method for add1, but that the method for alias is inherited from the lm class.

Does someone have a slick way to do this, or does it already exist?

PS Steve Walker's S3-S4-reference class glossary shows that this works automatically for reference classes, where we have to use an object to get the methods (x$getRefClass()$methods()).


Solution

  • Here's an attempt to replicate the "standard" behavior

    classMethods <- function(cl) {
        if(!is.character(cl)) {
            cl<-class(cl)
        }
        ml<-lapply(cl, function(x) {
            sname <- gsub("([.[])", "\\\\\\1", paste0(".", x, "$"))
            m <- methods(class=x)
            data.frame(
                m=as.vector(m), 
                c=x, n=sub(sname, "", as.vector(m)),
                attr(m,"info"),
                stringsAsFactors=F
            )
        })
        df<-do.call(rbind, ml)
        df<-df[!duplicated(df$n),]
        structure(df$m, 
            info=data.frame(visible=df$visible, from=df$from), 
            class="MethodsFunction")
    }
    

    And then you can try it out with

    g <- glm(y~x,data=data.frame(x=1:10,y=1:10))
    classMethods(g)
    #or classMethods(c("glm","lm"))
    

    and that will return

     [1] add1.glm*           anova.glm           confint.glm*        cooks.distance.glm*
     [5] deviance.glm*       drop1.glm*          effects.glm*        extractAIC.glm*    
     [9] family.glm*         formula.glm*        influence.glm*      logLik.glm*        
    [13] model.frame.glm     nobs.glm*           predict.glm         print.glm          
    [17] residuals.glm       rstandard.glm       rstudent.glm        summary.glm        
    [21] vcov.glm*           weights.glm*        alias.lm*           case.names.lm*     
    [25] dfbeta.lm*          dfbetas.lm*         dummy.coef.lm*      hatvalues.lm       
    [29] kappa.lm            labels.lm*          model.matrix.lm     plot.lm            
    [33] proj.lm*            qr.lm*              simulate.lm*        variable.names.lm* 
    
       Non-visible functions are asterisked
    

    It's not as elegant or short as Josh's, but I think its a good recreation of the default behavior. It's funny to see that the methods function is itself mostly just a grep across all known function names. I borrowed the gsub stuff from there.