Dear Developers, In current implementation of validity method, objects are first coerced to superclass (slots are striped). Thus, it is not possible to write validity method which would perform some checks on children slots. Say, I want to check if number of slots in a class is equal to "n": setClass("A", representation(a="numeric", n="integer"), prototype=list(a=12, n=1L), validity=function(object){ if(length(slotNames(object))!=object at n+1) paste("Number of slots must be ", object at n) else TRUE }) setClass("B", representation(b="numeric"), contains="A", prototype=list(a=12, b=14, n=2L)) new("B", a=11, b=33) Error in validObject(.Object) : invalid class "B" object: Number of slots must be 2 Error, because an object of class "A" is passed to validObject with one slot "b" removed and n=2. Is were a work around for this, or I am just doomed to write the same validity method for each children class? Many thanks, Vitalie. --
"Vitalie S." <vitosmail at rambler.ru> writes:> Dear Developers, > > In current implementation of validity method, objects are first > coerced to superclass (slots are striped). Thus, it is not possible > to write validity method which would perform some checks on children > slots. > > Say, I want to check if number of slots in a class is equal to "n": > > setClass("A", representation(a="numeric", n="integer"), > prototype=list(a=12, n=1L), > validity=function(object){ > if(length(slotNames(object))!=object at n+1) paste("Number > of slots must be ", object at n) > else TRUE > }) > > > setClass("B", representation(b="numeric"), contains="A", > prototype=list(a=12, b=14, n=2L)) > > > new("B", a=11, b=33) > Error in validObject(.Object) : > invalid class "B" object: Number of slots must be 2 > > Error, because an object of class "A" is passed to validObject with > one slot "b" removed and n=2. > > Is were a work around for this, or I am just doomed to write the same > validity method for each children class?I think you're doomed, but checking the number of slots in an instance seems like a very unusual validity method -- isn't this the job of the methods package, not your implementation of particular classes? Martin> Many thanks, > Vitalie.-- Martin Morgan Computational Biology / Fred Hutchinson Cancer Research Center 1100 Fairview Ave. N. PO Box 19024 Seattle, WA 98109 Location: Arnold Building M1 B861 Phone: (206) 667-2793
Vitalie S.
2009-Aug-20 13:29 UTC
[Rd] S4: inheritance of validity methods? + Inconsistency in order of validity checks.
With the help of Martin Morgan here is the solution for the above question. First create VIRTUAL class with all the test for children classes: setClass("TESTS", validity=function(object) { cat("Validity here:", class(object), "\n") TRUE }) .simple <- function(object) { cat("No validity -", class(object), "\n") TRUE } setClass("A", representation(a="numeric", n="integer"), validity=.simple) setClass("B", representation("A", b="numeric"), validity=.simple) setClass("C", representation("B", c="numeric"), validity=.simple) Set each children to inherit from TESTS class: setIs("B", "TESTS") setIs("C", "TESTS") Now we have exactly what we wanted, validity tests are executed only once:> res <- new("B", b=1)Validity here: B No validity - A No validity - B> res <- new("C", c=1)No validity - A Validity here: C No validity - B No validity - C The order in which validity is called above is somewhat counter intuitive. For class "C" complete hierarchy is this:> superClassDepth(getClass("C"))$label[1] "B" "TESTS" "A" "TESTS" "TESTS" so if validity would start bottomup then TEST should be the first to follow. And vector of unique superclasses would be c("B", "A", "TEST"). Instead validity uses the vector of unique labels constructed *TOPDOWN* :> getAllSuperClasses(getClass("C"))[1] "B" "TESTS" "A" Apparently this is an inconsistency in implementation, isn't it? Vitalie. On Mon, 17 Aug 2009 20:06:44 +0200, Vitalie S. <vitosmail at rambler.ru> wrote:> Dear Developers, > > In current implementation of validity method, objects are first coerced > to superclass (slots are striped). Thus, it is not possible to write > validity method which would perform some checks on children slots. > > Say, I want to check if number of slots in a class is equal to "n": > > setClass("A", representation(a="numeric", n="integer"), > prototype=list(a=12, n=1L), > validity=function(object){ > if(length(slotNames(object))!=object at n+1) paste("Number of > slots must be ", object at n) > else TRUE > }) > > > setClass("B", representation(b="numeric"), contains="A", > prototype=list(a=12, b=14, n=2L)) > > > new("B", a=11, b=33) > Error in validObject(.Object) : > invalid class "B" object: Number of slots must be 2 > > Error, because an object of class "A" is passed to validObject with one > slot "b" removed and n=2. > > Is were a work around for this, or I am just doomed to write the same > validity method for each children class? > > Many thanks, > Vitalie. > > -- > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel--