% File src/library/methods/man/validObject.Rd
% Part of the R package, https://www.R-project.org
% Copyright 1995-2017 R Core Team
% Distributed under GPL 2 or later

\name{validObject}
\alias{validObject}
\alias{getValidity}
\alias{setValidity}
\title{ Test the Validity of an Object }
\description{
  \code{validObject()} tests the validity of \code{object} related to
  its class definition; specifically, it checks that all slots
  specified in the class definition are present and that the object in
  the slot is from the required class or a subclass of that class.

  If the object is valid, \code{TRUE} is returned; otherwise, an error
  is generated, reporting all the validity failures encountered.
If argument \code{test} is
  \code{TRUE}, the errors are returned as a character vector rather
  than generating an error.
  

  When an object from a class is initialized, the default method for
  \code{\link{initialize}()} calls \code{validObject}.

A class definition may have a validity method, set by a call to
  the function \code{setValidity}, in the package or environment that
  defines the class (or via the \code{validity} argument to \code{\link{setClass}}).  The method
  should be a function of one object that returns \code{TRUE} or a character-string
  description of the non-validity.
  If such a method exists, it will be called from \code{validObject}
  and any strings from failure will be included in the result or the
  error message.
Any validity methods defined for superclasses (from the \code{contains=}
argument to \code{\link{setClass}}), will also be called.


}
\usage{
validObject(object, test = FALSE, complete = FALSE)

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

getValidity(ClassDef)
}
\arguments{
  \item{object}{ any object, but not much will happen unless the
    object's class has a formal definition.}
  \item{test}{logical; if \code{TRUE} and validity fails, the
    function returns a vector of strings describing the problems.  If
    \code{test} is \code{FALSE} (the default) validity failure generates
    an error.}
  \item{complete}{logical; if \code{TRUE}, \code{validObject} is
      called recursively for each of the slots.  The default is \code{FALSE}.}
  \item{Class}{the name or class definition of the class whose validity
    method is to be set.}
  \item{ClassDef}{a class definition object, as from
    \code{\link{getClassDef}}.}
  \item{method}{a validity method;  that is, either \code{NULL} or a
    function of one argument (\code{object}).  Like
    \code{validObject}, the function should return \code{TRUE} if the
    object is valid, and one or more descriptive strings if any problems
    are found.  Unlike \code{validObject}, it should never generate an
    error.
  }
  \item{where}{an environment to store the modified class
      definition. Should be omitted, specifically  for calls from a package that defines the class.
    The definition will be stored in the
    namespace of the package.}

}
\section{Validity methods}{
 A validity method must be a function of one argument; formally, that
argument should be named \code{object}.
If the argument has a different name, \code{setValidity} makes the
substitution but in obscure cases that might fail, so it's wiser to
name the
 argument \code{object}.

A good method checks all the possible errors and returns a character
vector citing all the exceptions found, rather than returning after
the first one.
\code{validObject} will accumulate these errors in its error message
or its return value.

Note that validity methods do not have to check validity of
  superclasses: \code{validObject} calls such methods explicitly.
}
\details{
  Validity testing takes place \sQuote{bottom up}, checking the slots,
  then the superclasses, then the object's own validity method, if
  there is one.

For each slot and superclass, the existence of the specified class is
checked.
For each slot, the object in the slot is tested for inheritance from
the corresponding class.
If  \code{complete} is \code{TRUE},   \code{validObject} is called
recursively for the object in the slot.

Then, for each of the classes that this class
  extends (the \sQuote{superclasses}), the explicit validity method of
  that class is called, if one exists.  Finally, the validity method of
  \code{object}'s class is called, if there is one.

}
\value{
  \code{validObject} returns \code{TRUE} if the object is valid.
  Otherwise a vector of strings describing problems found, except that
  if \code{test} is \code{FALSE}, validity failure generates an error,
  with the corresponding strings in the error message.
}
\references{
Chambers, John M. (2016)
 \emph{Extending R},
  Chapman & Hall.
(Chapters 9 and 10.)
}
\seealso{\code{\link{setClass}};
  class \code{\linkS4class{classRepresentation}}.
}
\examples{
setClass("track",
          slots = c(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
\dontrun{try(validObject(t2))}
\dontshow{stopifnot(is(try(validObject(t2)), "try-error"))}

setClass("trackCurve", contains = "track",
         slots = c(smooth = "numeric"))

## all superclass validity methods are used when validObject
## is called from initialize() with arguments, so this fails
\dontrun{trynew("trackCurve", t2)}
\dontshow{stopifnot(is(try(new("trackCurve", t2)), "try-error"))}

setClass("twoTrack", slots = c(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
\dontrun{try(validObject(tT, complete = TRUE))}
\dontshow{stopifnot(is(try(validObject(tT, complete = TRUE)), "try-error"))}
}
\keyword{programming}
\keyword{classes}
