Reputation: 23154
Suppose I have a function like this:
myf = function(x) {
res = dostuff(x)
res # this is a data.frame
}
I want to do something special about res
, for example,
I want to make some generic functions like print.myf, summary.myf, ...
, so I can go ahead and give it a class:
myf = function(x) {
res = dostuff(x)
class(res) = 'myf'
res
}
But this way I cannot use it as a data.frame any more.
Upvotes: 5
Views: 918
Reputation: 193687
Here's an example with rle
. The rle
function creates a list
, but it doesn't have the class list
, so methods like as.data.frame
won't work "out of the box". As such, I've changed the last line to add "list"
as one of the classes.
x <- c(1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3)
rle2 <- function (x)
{
if (!is.vector(x) && !is.list(x))
stop("'x' must be an atomic vector")
n <- length(x)
if (n == 0L)
return(structure(list(lengths = integer(), values = x),
class = "rle"))
y <- x[-1L] != x[-n]
i <- c(which(y | is.na(y)), n)
## THE FOLLOWING IS FROM THE BASE RLE. NOTICE ONLY ONE CLASS...
# structure(list(lengths = diff(c(0L, i)), values = x[i]),
# class = "rle")
structure(list(lengths = diff(c(0L, i)), values = x[i]),
class = c("rle", "list"))
}
As you can see, I've simply changed the class
. The rest of the function is the same.
rle(x)
# Run Length Encoding
# lengths: int [1:3] 4 3 7
# values : num [1:3] 1 2 3
data.frame(rle(x))
# Error in as.data.frame.default(x[[i]], optional = TRUE, stringsAsFactors = stringsAsFactors) :
# cannot coerce class ""rle"" to a data.frame
rle2(x)
# Run Length Encoding
# lengths: int [1:3] 4 3 7
# values : num [1:3] 1 2 3
data.frame(rle2(x))
# lengths values
# 1 4 1
# 2 3 2
# 3 7 3
Of course, if we know this, we could also explicitly specify our methods if we know one exists:
as.data.frame.list(rle(x))
# lengths values
# 1 4 1
# 2 3 2
# 3 7 3
Upvotes: 3
Reputation: 368629
Yes, my standard (simple) example is
R> now <- Sys.time()
R> class(now)
[1] "POSIXct" "POSIXt"
R> class(as.POSIXlt(now))
[1] "POSIXlt" "POSIXt"
R>
It is also the reason behind the pro tip of testing with inherits("someClass")
rather than testing the result of class(obj)=="someClass"
.
Upvotes: 4