S4 class is not subsettable

r s4
HBat picture HBat · Aug 23, 2014 · Viewed 16.8k times · Source

I am trying to write a subsetting method for an S4 class. I get this S4 class is not subsettable error whatever I tried.

Here is a minimal example:

setClass(Class = "A", representation = representation(ID = "character"))
setClass(Class = "B", representation = representation(IDnos = "list"))

a1 <- new(Class = "A", ID = "id1")
a2 <- new(Class = "A", ID = "id2")

B1 <- new(Class = "B", IDnos = c(a1, a2))

When I type:

B1@IDnos[[1]]

I get what I want:

> An object of class "A"
> Slot "ID":
> [1] "id1"

But I want to get this by just writing something like: B1[1] or if not by B1[[1]]

From THIS post, I got some idea and tried to mimic what author wrote. But it didn't work in my case:

setMethod("[", c("B", "integer", "missing", "ANY"),
          function(x, i, j, ..., drop=TRUE)
          {
            x@IDnos[[i]]
            # initialize(x, IDnos=x@IDnos[[i]])    # This did not work either
          })
B1[1]

> Error in B1[1] : object of type 'S4' is not subsettable

Following code did not work either:

setMethod("[[", c("B", "integer", "missing"),
          function(x, i, j, ...)
          {
            x@IDnos[[i]]
          })
B1[[1]]

> Error in B1[[1]] : this S4 class is not subsettable

Any ideas?

Answer

MrFlick picture MrFlick · Aug 23, 2014

I think your problem is your signature is too strict. You are requiring an "integer" class. By default

class(1)
# [1] "numeric"

So it's not actually a true "integer" data.type. But when you do actually specify an integer literal

class(1L)
# [1] "integer"

B1[1L]
# An object of class "A"
# Slot "ID":
# [1] "id1"

So it might be better to use the more general signature of

setMethod("[", c("B", "numeric", "missing", "ANY"), ... )

which would allow your original attempts to work

B1[2]
# An object of class "A"
# Slot "ID":
# [1] "id2"