I have a custom S3 class foo, which adds some custom behavior on top of a normal data.frame:
foo_object <- data.frame()
class(foo_object) <- c("foo", "data.frame")
For this class there should also be a list class foo_list to store many of these foo objects.
foo_list_object <- list()
class(foo_list_object) <- c("foo_list", "list")
If you apply a subsetting operation for multiple elements on a list like this via foo_list_object[c(1,2,3)] you get an object only of class list. But I want it to remain a foo_list.
Hadley says you should implement custom accessor functions for vector classes to achieve this behavior:
When implementing a vector class, you should implement these methods: length, [, [<-, [[, [[<-, c. (If [ is implemented rev, head, and tail should all work).
My question concerning this has three parts:
- What's the best way to implement custom accessor functions for S3 classes? Can I rely on the underlying primitive class?
- Which accessor functions do I need in my case? I think I don't need to define
[[,[<-,[[<-or$because in these cases the inherited functionality oflistbehaves correctly also forfoo_list. Should I implement them anyway? - How can I implement an operator with 3 arguments like
[<-or[[<-? You need the object, the index and the new value?
The following code for [ seems to work:
`[.foo_list` <- function(x, i) {
class(x) <- "list"
as.foo_list(x[i])
}
This on the other hand doesn't:
`[[<-.foo_list` <- function(x, i, y) {
if (!is.foo(y)) {
stop("Please provide an object of class foo.")
}
x[[i]] <- y
}
How can I fix this (1./3.) and do I even have to (2.)?