Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you get S3 methods to work with S4 objects?

Tags:

oop

r

r-s3

r-s4

I'm writing an S3 method that I want to work with any R object, including S4 objects.

The first thing I don't understand is that S4 classes don't appear to derive from an S4 base class, so given f <- function(x) UseMethod("f") I can't just declare an f.S4 dispatch method and have it pick up all S4 objects. (Although if you unclass an S4 object, it does seem to be given class S4.) How should I manage the dispatching?

It seems that the easiest way to deal with these S4 objects would be to convert them to be lists. Unfortunately, as.list throws an error ("no method for coercing this S4 class to a vector").

This is my test S4 object:

library(gWidgetstcltk)
win <- gwindow()

The functions S3Part and S3Class in the methods package looked promising, but they both throw errors when I use them on win. So, question 2 is: Is there a general way of converting S4 objects to lists?

like image 616
Richie Cotton Avatar asked May 06 '11 14:05

Richie Cotton


Video Answer


1 Answers

S4 is a superclass (virtual class, whatever, somebody please chime in with the correct name) that cannot be used directly dispatching. Same for S3 by the way. You can do S3-dispatching for S4 classes the way you do with S3 classes. On a sidenote, if nothing is specified then calling myfun on an S4 object will just lead to the .default function. :

myfun <- function(object, ...) UseMethod("myfun")

myfun.default <- function(object,...){
    cat("default method.\n")
    print(object)
}

myfun.gWindow <- function(object,...){
    cat("Here here...")
    print(object)
}

x <- 1:10
myfun(x)
myfun(win)
rm(myfun.gWindow)
myfun(win)

If you want to catch all S4 methods, you can dispatch manually in your .default function or generic function, using isS4(). Adding the dispatching in the .default function allows for automatic S3 dispatching to some S4 classes. If you add it in the generic, you just dispatch to all S4 no-matter-what :

    myfun.default <- function(object,...){
        if(isS4(object)) myfun.S4(object,...)
        else {
          cat("default method.\n")
          print(object)
        }
    }

    myfun.S4 <- function(object,...){
        cat("S4 method\n")
        print(object)
    }

x <- 1:10
myfun(x)
myfun(win)

Regarding your second question: gWindow is a special case. It also returns an error when tried with str(win). I don't know the exact structure, but it's definitely not a normal S4 object.

like image 143
Joris Meys Avatar answered Oct 12 '22 11:10

Joris Meys