validObject             package:methods             R Documentation

Test the Validity of an Object

Description:

     The validity of 'object' related to its class definition is
     tested.  If the object is valid, 'TRUE' is returned; otherwise,
     either a vector of strings describing validity failures is
     returned, or an error is generated (according to whether 'test' is
     'TRUE').  Optionally, all slots in the object can also be
     validated.

     The function 'setValidity' sets the validity method of a class
     (but more normally, this method will be supplied as the 'validity'
     argument to 'setClass').  The method should be a function of one
     object that returns 'TRUE' or a description of the non-validity.

Usage:

     validObject(object, test = FALSE, complete = FALSE)

     setValidity(Class, method, where = topenv(parent.frame()) )

     getValidity(ClassDef)

Arguments:

  object: any object, but not much will happen unless the object's
          class has a formal definition.

    test: logical; if 'TRUE' and validity fails, the function returns a
          vector of strings describing the problems.  If 'test' is
          'FALSE' (the default) validity failure generates an error.

complete: logical; if 'TRUE', validity methods will be applied
          recursively to any of the slots that have such methods.

   Class: the name or class definition of the class whose validity
          method is to be set.

ClassDef: a class definition object, as from 'getClassDef'.

  method: a validity method;  that is, either 'NULL' or a function of
          one argument ('object').  Like 'validObject', the function
          should return 'TRUE' if the object is valid, and one or more
          descriptive strings if any problems are found.  Unlike
          'validObject', it should never generate an error. 

   where: the modified class definition will be stored in this
          environment.


     Note that validity methods do not have to check validity of
     superclasses: the logic of 'validObject' ensures these tests are
     done once only.  As a consequence, if one validity method wants to
     use another, it should extract and call the method from the other
     definition of the other class by calling 'getValidity()': it
     should _not_ call 'validObject'.

Details:

     Validity testing takes place 'bottom up': Optionally, if
     'complete=TRUE', the validity of the object's slots, if any, is
     tested.  Then, in all cases, for each of the classes that this
     class extends (the 'superclasses'), the explicit validity method
     of that class is called, if one exists.  Finally, the validity
     method of 'object''s class is called, if there is one.

     Testing generally stops at the first stage of finding an error,
     except that all the slots will be examined even if a slot has
     failed its validity test.

     The standard validity test (with 'complete=FALSE') is applied when
     an object is created via 'new' with any optional arguments
     (without the extra arguments the result is just the class
     prototype object).

     An attempt is made to fix up the definition of a validity method
     if its argument is not 'object'.

Value:

     'validObject' returns 'TRUE' if the object is valid. Otherwise a
     vector of strings describing problems found, except that if 'test'
     is 'FALSE', validity failure generates an error, with the
     corresponding strings in the error message.

References:

     Chambers, John M. (2008) _Software for Data Analysis: Programming
     with R_ Springer.  (For the R version.)

     Chambers, John M. (1998) _Programming with Data_ Springer (For the
     original S4 version.)

See Also:

     'setClass'; class 'classRepresentation'.

Examples:

     setClass("track",
               representation(x="numeric", y = "numeric"))
     t1 <- new("track", x=1:10, y=sort(stats::rnorm(10)))
     ## A valid "track" object has the same number of x, y values
     validTrackObject <- function(object) {
         if(length(object@x) == length(object@y)) TRUE
         else paste("Unequal x,y lengths: ", length(object@x), ", ",
                    length(object@y), sep="")
     }
     ## assign the function as the validity method for the class
     setValidity("track", validTrackObject)
     ## t1 should be a valid "track" object
     validObject(t1)
     ## Now we do something bad
     t2 <- t1
     t2@x <- 1:20
     ## This should generate an error
     ## Not run: try(validObject(t2))


     setClass("trackCurve",
              representation("track", smooth = "numeric"))

     ## all superclass validity methods are used when validObject
     ## is called from initialize() with arguments, so this fails
     ## Not run: trynew("trackCurve", t2)


     setClass("twoTrack", representation(tr1 = "track", tr2 ="track"))

     ## validity tests are not applied recursively by default,
     ## so this object is created (invalidly)
     tT  <- new("twoTrack", tr2 = t2)

     ## A stricter test detects the problem
     ## Not run: try(validObject(tT, complete = TRUE))

