Sources on S4 Objects, Methods and Programming in R

Sources on S4 objects, methods and programming in R

My write up of S4 (still in progress) is available here: http://adv-r.had.co.nz/S4.html

In R, how can one make a method of an S4 object that directly adjusts the values inside the slots of that object?

I asked this question on the R-list myself, and found a work-around to simulate a pass by reference, something in the style of :

eval(
eval(
substitute(
expression(object@slot <<- value)
,env=parent.frame(1) )
)
)

Far from the cleanest code around I'd say...

A suggestion coming from the R-help list, uses an environment to deal with these cases.
EDIT : tweaked code inserted.

setClass("MyClass", representation(.cache='environment',masterlist="list"))

setMethod("initialize", "MyClass",
function(.Object, .cache=new.env()) {
.Object@masterlist <- list()
callNextMethod(.Object, .cache=.cache)
})

sv <- function(object,name,value) {} #store value

setMethod("sv",signature=c("MyClass","character","vector"),
function(object, name, value) {
object@.cache$masterlist[[name]] <- value
})

rv <- function(object,name) {} #retrieve value

setMethod("rv",signature=c("MyClass","character"),
function(object, name) {
return(object@.cache$masterlist[[name]])
})

How do I show the source code of an S4 function in a package?

Use getMethod() and specify the signature. In your case, that could be eg :

getMethod("GenTable","topGOdata")

to show the GenTable method for topGOdata objects. In this case, there is only a method defined for topGOdata objects. In case there are methods with different signatures, showMethods() will tell you which ones. In your case :

showMethods("GenTable")
# Function: GenTable (package topGO)
# object="topGOdata"

You can get the code for the signature you want by specifying it in the getMethod() function.

class in R: S3 vs S4

S3 can only dispatch on it's first argument, whereas S4 can dispatch on multiple arguments. If you want to be able to write methods for function foo that should do different things if given an object of class "bar" or given objects of class "bar" and "foobar", or given objects of class "barfoo" and "foobar", then S4 provides a far better way to handle such complexities.

S3 is very simple and easy to implement, but isn't really a formal object oriented system. That simplicity comes at the cost of enforcing that objects belonging to a class have the correct components/slots etc. With S3 I can do things like class(obj) <- "lm" and method dispatch will use methods for the "lm" class when passed obj, but there is no guarantee that obj really is an object of class "lm".

S3 is easy to implement, document and requires less extra knowledge on the part of the programmer.

Which to use can only be something you can decide. Doug Bates (2003) has said, for example, that for new projects he would use S4 over S3. I haven't yet had a need to use anything other than S3 methods.

So I would sit down and think about the sorts of classes and methods you want to operate on those classes. Think about the functionality you want, and that will probably point towards one system or the other.

Douglas Bates. Converting packages to S4. R News, 3(1):6-8, June 2003

How can I get a list of all methods defined on an S4 class in R?

Maybe this would be useful:

mtext <-  showMethods(class="SpatialPolygons", printTo =FALSE )
fvec <- gsub( "Function(\\:\\s|\\s\\\")(.+)(\\s\\(|\\\")(.+$)",
"\\2", mtext[grep("^Function", mtext)] )
fvec
[1] ".quad" "[" "addAttrToGeom"
[4] "area" "as.data.frame" "click"
[7] "coerce" "coordinates" "coordnames"
[10] "coordnames<-" "coords" "disaggregate"
[13] "extract" "fromJSON" "isDiagonal"
[16] "isTriangular" "isValidJSON" "jsType"
[19] "over" "overlay" "plot"
[22] "polygons" "polygons<-" "rasterize"
[25] "recenter" "spChFIDs" "spsample"
[28] "spTransform" "text" "toJSON"

The original version did not properly extract the quoted non S4 generics in mtext such as:

 [60] "Function \"jsType\":"                                     
[61] " <not an S4 generic function>"

How to write a large list with S4 objects as a CSV file?

The GeneOverlap package has several get* functions for accessing test result statistics. You can combine this with the tidyverse to create a tidy table of results:

results <- tibble(pheno = names(tests), tests = tests) %>% 
rowwise() %>%
mutate(
across(tests,
.fns = list(tested = getTested, pval = getPval, OR = getOddsRatio, jaccard = getJaccard),
.names = '{.fn}')
) %>%
select(-tests) # drop test object column

pheno tested pval OR jaccard
<chr> <lgl> <dbl> <dbl> <dbl>
1 Phenotype1 TRUE 0.00481 410. 0.2
2 Phenotype2 TRUE 0.00214 1302. 0.333
3 Phenotype6 TRUE 1 0 0

You can then save this data frame with write_csv or a similar method.



Related Topics



Leave a reply



Submit