mathematical.coffee
mathematical.coffee

Reputation: 56905

How to see if an object has a particular method?

I would like to know if a given object has a particular method. For example, suppose I want to know whether my mystery object has a specific print method. From reading ?methods, I try something like this:

has.print <- function (mysteryObject) {
    'print' %in% attr(methods(class=class(mysteryObject)), 'info')$generic
}

m <- lm(Sepal.Length ~ Species, iris)
class(m) # 'lm'
has.print(m)

This is fine if mysteryObject has just one class. If it has multiple, there are problems in methods. I can get around this by using class(mysteryObject)[1], so that (for example)

library(data.table)
class(test) # data.table, data.frame
test <- data.table(iris)
has.print(test) # TRUE since there's a print.data.table

However, if I have something with multiple classes but the first does not have a print method, this returns false. Example:

mlm <- lm(cbind(Petal.Length, Petal.Width) ~ Species, iris)
class(mlm) # 'mlm', 'lm'. Note there is no print.mlm but there's a print.lm
has.print(mlm) # FALSE

This returns FALSE as there is no print.mlm. However, there is a print.lm, that is used instead, so I would like this to return TRUE.

Speaking as someone who knows very little about S3, S4, etc, is there a "proper" way to see if an object has a 'print' method on any of its classes? Ideally this works for both S3 and S4 objects, though I do not know what this means.

I can vectorise my methods(class=...) over class(mysteryObject), but I bet there's a more appropriate way to do it...

Upvotes: 4

Views: 184

Answers (1)

bergant
bergant

Reputation: 7232

Apply methods on every class, unlist and search for "print":

has.print <- function(object) {
  "print" %in% 
    unlist(
      lapply(
        class(object), 
        function(x) attr(methods(class = x), "info")$generic)
    )
}

It is possible to start from the other side (searching for a class in all generic print functions):

has.print <- function(object) {
  any( sprintf("print.%s", class(object)) %in% 
         rownames(attr(methods(generic.function = "print"), "info")))
}

To find the method:

which.print <- function(object) {
  print_methods <- rownames(attr(methods(generic.function = "print"), "info"))
  print_methods[print_methods %in% sprintf("print.%s", class(object))]
}

# > which.print(mlm)
# [1] "print.lm"

S4

S4 classes are "printed" with show method. If no specialized method exists the showDefault is called. Function showMethods will show if there is any specialized show:

For example:

library(Matrix)
showMethods(f = "show", class = "denseMatrix")

#> Function: show (package methods)
#> object="denseMatrix"

showDefault is also calling print for non S4 members.

Upvotes: 2

Related Questions