Bojanowski, M.J. (Michal)
2007-Jul-25 01:16 UTC
[R] initalizing and checking validity of S4 classes
Dear useRs and wizaRds, I am currently developing a set of functions using S4 classes. On the way I encountered the problem exemplified with the code below. For some reason the 'validity' method does not seem to work, i.e. does not check for errors in the specification of the slots of the defined class. Any hints? My understanding of the whole S4 system was that validity checks are made *after* class initialization. Is that correct? Thanks a lot in advance! PS. Session info: R version 2.5.1 (2007-06-27) i386-pc-mingw32 locale: LC_COLLATE=Polish_Poland.1250;LC_CTYPE=Polish_Poland.1250;LC_MONETARY=Polish_Poland.1250;LC_NUMERIC=C;LC_TIME=Polish_Poland.1250 attached base packages: [1] "stats" "graphics" "grDevices" "utils" "datasets" "methods" [7] "base">-b-e-g-i-n--r--c-o-d-e- setClass( "someclass", representation(v="numeric", l="character"), prototype( v=numeric(0), l=character(0) ) ) setMethod("initialize", "someclass", function(.Object, v=numeric(0), l=character(0)) { # strip the vector names cv <- v cl <- l names(cv) <- NULL names(cl) <- NULL rval <- .Object rval@v <- cv rval@l <- cl rval } ) # at this point this should be OK o <- new("someclass", v=1:2, l=letters[1:3]) o # check validity f <- function(object) { rval <- NULL if( length(object@v) != length(object@l) ) rval <- c( rval, "lengths dont match") if( is.null(rval) ) return(TRUE) else return(rval) } # this should return error description f(o) # define the validity method setValidity( "someclass", f) # this should return an error new("someclass", v=1:2, l=letters[1:3]) # but it doesn't... -e-n-d--r--c-o-d-e- ____________________________________ Michal Bojanowski ICS / Department of Sociology Utrecht University Heidelberglaan 2; 3584 CS Utrecht Room 1428 m.j.bojanowski at uu dot nl http://www.fss.uu.nl/soc/bojanowski/ [[alternative HTML version deleted]]
Hi Michal -- Add validObject to your initialize method:> setMethod("initialize", "someclass",+ function(.Object, v=numeric(0), l=character(0)) + { + # strip the vector names + cv <- v + cl <- l + names(cv) <- NULL + names(cl) <- NULL + rval <- .Object + rval at v <- cv + rval at l <- cl + validObject(rval) + rval + } ) [1] "initialize"> new("someclass", v=1:2, l=letters[1:3])Error in validObject(rval) : invalid class "someclass" object: lengths dont match Note that without initialize, we have:> setClass("A",+ representation=representation( + v="numeric", l="character")) [1] "A"> setValidity("A", f)Slots: Name: v l Class: numeric character> new("A", v=1:2, l=letters[1:3])Error in validObject(.Object) : invalid class "A" object: lengths dont match Here are two interpretations of this. (1) using 'initialize' means that you are taking control of the initialization process, and hence know when you need to call validObject. (2) Responsibility for object validity is ambiguous -- does it belong with 'new', 'initialize', or a 'constructor' that the programmer might write? This is particularly problematic with R's copy semantics, where creating transiently invalid objects seems to be almost necessary (e.g., callNextMethod() in 'initialize' might initialize the inherited slots of the object, but the object itself is of the derived class and could well be invalid 'invalid' after the base class has finished with initialize). Martin "Bojanowski, M.J. (Michal)" <M.J.Bojanowski at uu.nl> writes:> Dear useRs and wizaRds, > > I am currently developing a set of functions using S4 classes. On the way I encountered the problem exemplified with the code below. For some reason the 'validity' method does not seem to work, i.e. does not check for errors in the specification of the slots of the defined class. Any hints? > > My understanding of the whole S4 system was that validity checks are made *after* class initialization. Is that correct? > > Thanks a lot in advance! > > PS. Session info: > > R version 2.5.1 (2007-06-27) > i386-pc-mingw32 > > locale: > LC_COLLATE=Polish_Poland.1250;LC_CTYPE=Polish_Poland.1250;LC_MONETARY=Polish_Poland.1250;LC_NUMERIC=C;LC_TIME=Polish_Poland.1250 > > attached base packages: > [1] "stats" "graphics" "grDevices" "utils" "datasets" "methods" > [7] "base" >> > > > > > -b-e-g-i-n--r--c-o-d-e- > > setClass( "someclass", representation(v="numeric", l="character"), > prototype( v=numeric(0), > l=character(0) ) > ) > > setMethod("initialize", "someclass", > function(.Object, v=numeric(0), l=character(0)) > { > # strip the vector names > cv <- v > cl <- l > names(cv) <- NULL > names(cl) <- NULL > rval <- .Object > rval at v <- cv > rval at l <- cl > rval > } ) > > # at this point this should be OK > o <- new("someclass", v=1:2, l=letters[1:3]) > o > > # check validity > f <- function(object) > { > rval <- NULL > if( length(object at v) != length(object at l) ) > rval <- c( rval, "lengths dont match") > if( is.null(rval) ) return(TRUE) > else return(rval) > } > > # this should return error description > f(o) > > > # define the validity method > setValidity( "someclass", f) > > # this should return an error > new("someclass", v=1:2, l=letters[1:3]) > > # but it doesn't... > > -e-n-d--r--c-o-d-e- > > > > > ____________________________________ > Michal Bojanowski > ICS / Department of Sociology > Utrecht University > Heidelberglaan 2; 3584 CS Utrecht > Room 1428 > m.j.bojanowski at uu dot nl > http://www.fss.uu.nl/soc/bojanowski/ > > > [[alternative HTML version deleted]] > > ______________________________________________ > 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 > and provide commented, minimal, self-contained, reproducible code.-- Martin Morgan Bioconductor / Computational Biology http://bioconductor.org
Bojanowski, M.J. (Michal)
2007-Jul-25 20:49 UTC
[R] initalizing and checking validity of S4 classes
Dear Martin and Seth, Thanks a million for explanations and suggestions. I find myself still in the process of learning S4 system. Can you possibly suggest some material that I could use in this "process"? Anything apart from "Programming with data" book? I also know the notes written by John Chambers and I also have Fritz Leisch's slides from the first UseR!, all three available on the Web. Do you have any suggestions in that matter? Thanks a lot in advance! Best, Michal> Martin Morgan <mtmorgan at fhcrc.org> writes: > > > Hi Michal -- > > > > Add validObject to your initialize method: > > Actually, a call to valid object is part of the default initialization > method which has been masked. A different solution, which might have > some other benefits is to delegate back to the default method using > callNextMethod. So you could do: > > setMethod("initialize", "someclass", > function(.Object, v=numeric(0), l=character(0)) > { > # strip the vector names > > cv <- v > cl <- l > names(cv) <- NULL > names(cl) <- NULL > callNextMethod(.Object=.Object, v=cv, l=cl) > } ) > > > > Here are two interpretations of this. (1) using 'initialize' means > > that you are taking control of the initialization process, and hence > > know when you need to call validObject. > > Yes. Anytime you specialize a method you must take responsibility for > any less specific methods. In this case, the default 'initialize' > does object validation. So if you want validation, you either need to > do it directly or invoke the default method. > > > (2) Responsibility for object > > validity is ambiguous -- does it belong with 'new', 'initialize', or a > > 'constructor' that the programmer might write? This is particularly > > problematic with R's copy semantics, where creating transiently > > invalid objects seems to be almost necessary (e.g., callNextMethod() > > in 'initialize' might initialize the inherited slots of the object, > > but the object itself is of the derived class and could well be > > invalid 'invalid' after the base class has finished with initialize). > > This is a good point. It suggests that, at least, one must initialize > all non-inherited slots to valid values _before_ calling the next > method. > > + seth: :: ::: Note that my e-mail address has changed to m.j.bojanowski at uu dot nl ::: Please update you address books accordingly. Thank you! :: : ____________________________________ Michal Bojanowski ICS / Department of Sociology Utrecht University Heidelberglaan 2; 3584 CS Utrecht The Netherlands m.j.bojanowski at uu dot nl http://www.fss.uu.nl/soc/bojanowski/ [[alternative HTML version deleted]]
Reasonably Related Threads
- S4 method dispatch and namespaces: why is default method selected
- Was: setValidity and "initialize" method conflict ? [in R-help]
- Dramatic slowdown of R 2.7.2?
- inconsistent behaviour of add1 and drop1 with a weighted linear model
- Problem with S4 inheritance: unexpected re-initialization?