[R] Testing for S4 objects (redux)

John Fox jfox at mcmaster.ca
Sun Dec 5 00:19:04 CET 2004


Dear John,

I've encountered the following problem:

> x <- rnorm(100)
> y <- sample(2, 100, replace=TRUE)
> res <- by(x, y, mean)
> res
INDICES: 1
[1] 0.1129494
------------------------------------------------------------ 
INDICES: 2
[1] -0.2066684
> 
> isS4object <- function(object)(length(attr(object, "class"))==1 &&
+  !is.null(getClass(class(object))))
> 
> isS4object(res)
Error in getClass(class(object)) : "by" is not a defined class
> 

For a simple question, this has gotten rather complicated. Any suggestions
would be appreciated.

Regards,
 John

--------------------------------
John Fox
Department of Sociology
McMaster University
Hamilton, Ontario
Canada L8S 4M4
905-525-9140x23604
http://socserv.mcmaster.ca/jfox 
-------------------------------- 

> -----Original Message-----
> From: John Chambers [mailto:johnmchambers at gmail.com] 
> Sent: Tuesday, November 30, 2004 9:40 AM
> To: John Fox
> Cc: Martin Maechler; r-help at stat.math.ethz.ch
> Subject: Re: [R] Testing for S4 objects
> 
> Let me suggest a different test, because slotNames was 
> written to work differently when given a string or a class 
> definition.  With your definition,
> 
> R> x <- "classRepresentation"
> R> isS4object(x)
> [1] TRUE
> 
> which I assume is not what you wanted.  (Given a single string,
> slotNames() tries to look up the class definition of that name.)
> 
> How about the following?  The logic is that an S4 object must 
> have an actual class attribute of length 1 (that rules out 
> basic data types, where class(x) is a string but there is no 
> actual attribute, and also rules out some S3 objects).  Then 
> if that's true, try to look up the class definition.  If it 
> is non-null, seems like an S4 object.
> 
> R> isS4object <- function(object)(length(attr(object, "class"))==1 &&
> +     !is.null(getClass(class(object))))
> R> isS4object(x)
> [1] FALSE
> R> isS4object(getClass(class(x)))
> [1] TRUE
> 
> This definition seems to work, at least on the examples I 
> could think of right away.  Notice though, that some classes, 
> such as "ts", that have been around for a long while are 
> nevertheless legitimate S4 classes, so:
> 
> R> t1 = ts(1:12)
> R> isS4object(t1)
> [1] TRUE
> 
> (this applies to either version of isS4object).
> 
> There are a couple of details, more appropriate for the r-devel list. 
> Seems  a good candidate for a function to add to R.
> 
> 
> On Sat, 27 Nov 2004 17:48:30 -0500, John Fox <jfox at mcmaster.ca> wrote:
> > Dear Martin,
> > 
> > As it turns out, the test that I proposed (i.e., testing for NULL 
> > slotNames) sometimes fails. For example:
> > 
> > > library(car)
> > > data(Prestige)
> > > sum <- summary(lm(prestige ~ income + education, data=Prestige))
> > > slotNames(sum)
> > character(0)
> > 
> > The following, however, seems to work (at least as far as I've been 
> > able to
> > ascertain):
> > 
> > isS4object <- function(object) length(slotNames(object)) != 0
> > 
> > I hope that this is a more robust test.
> > 
> > 
> > 
> > John
> > 
> > --------------------------------
> > John Fox
> > Department of Sociology
> > McMaster University
> > Hamilton, Ontario
> > Canada L8S 4M4
> > 905-525-9140x23604
> > http://socserv.mcmaster.ca/jfox
> > --------------------------------
> > 
> > > -----Original Message-----
> > > From: Martin Maechler [mailto:maechler at stat.math.ethz.ch]
> > > Sent: Friday, November 26, 2004 3:18 AM
> > > To: John Fox
> > > Cc: r-help at stat.math.ethz.ch
> > > Subject: Re: [R] Testing for S4 objects
> > >
> > > >>>>> "JohnF" == John Fox <jfox at mcmaster.ca>
> > > >>>>>     on Thu, 25 Nov 2004 22:28:50 -0500 writes:
> > >
> > >     JohnF> Dear r-help list members, Is there a way to test
> > >     JohnF> whether an object is an S4 object? The best that I've
> > >     JohnF> been able to come up with is
> > >
> > >     JohnF>    isS4object <- function(object)
> > > !(is.null(slotNames(object)))
> > >
> > > you can drop one pair of "(..)" to give
> > >
> > >   isS4object <- function(object) !is.null(slotNames(object))
> > >
> > >
> > >     JohnF> which assumes that an S4 object has at least one
> > >     JohnF> slot. I think this is safe, but perhaps I'm missing
> > >     JohnF> something.
> > >
> > > The question is a very good one -- that I have posed to R-core a 
> > > while ago myself.
> > >
> > > Inside  utils:::str.default  {which doesn't show the many 
> commments 
> > > in the *source* of str.default()}, I have wanted a way that even 
> > > works when the 'methods' package is not attached and use the more 
> > > obscure
> > >
> > >     #NOT yet:if(has.class <- !is.null(cl <- class(object)))
> > >     if(has.class <- !is.null(cl <- attr(object, "class")))#
> > > S3 or S4 class
> > >       S4 <- !is.null(attr(cl, "package"))## <<<'kludge' FIXME!
> > >       ##or length(methods::getSlots(cl)) > 0
> > >
> > > For the time being, I'd keep your function, but I don't 
> think we'd 
> > > guarantee that it will remain the appropriate test in all 
> future.  
> > > But till then many things will have happened (if not all of them 
> > > ;-).
> > >
> > > Martin Maechler, ETH Zurich
> > >
> > 
> > ______________________________________________
> > R-help at stat.math.ethz.ch mailing list
> > https://stat.ethz.ch/mailman/listinfo/r-help
> > PLEASE do read the posting guide! 
> > http://www.R-project.org/posting-guide.html
> >




More information about the R-help mailing list