Rev 26266 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
\name{setClass}\alias{setClass}\alias{removeClass}\alias{resetClass}\alias{isClass}\alias{getClasses}\alias{findClass}\alias{sealClass}\title{Create a Class Definition}\description{Functions to create (\code{setClass}) and manipulate class definitions.}\usage{setClass(Class, representation, prototype, contains=character(),validity, access, where, version, sealed, package)removeClass(Class, where)isClass(Class, formal=TRUE, where)getClasses(where, inherits = missing(where))findClass(Class, where, unique = "")resetClass(Class, classDef, where)sealClass(Class, where)}\arguments{\item{Class}{ character string name for the class. Other than\code{setClass}, the functions will usually take a class definitioninstead of the string (allowing the caller to identify the class uniquely). }\item{representation}{ the slots that the new class should haveand/or other classes that this class extends. Usually a call tothe \code{\link{representation}} function. }\item{prototype}{ an object (usually a list) providing the defaultdata for the slots specified in the representation. }\item{contains}{ what classes does this class extend? (These arecalled \emph{superclasses} in some languages.) When these classeshave slots, all their slots will be contained in the new class aswell. }\item{where}{ For \code{setClass} and \code{removeClass}, theenvironment in which to store or remove thedefinition. Defaults to the top-level environment of the calling function(the global environment for ordinary computations, but theenvironment or namespace of a package when loading that package).For other functions, \code{where} defines where to do the searchfor the class definition, and the default is to search from the top-levelenvironment or namespace of the caller to this function.}\item{unique}{if \code{findClass} expects a unique location for theclass, \code{unique} is a character string explaining the purposeof the search (and is used in warning and error messages). Bydefault, multiple locations are possible and the function alwaysreturns a list.}\item{inherits}{in a call to \code{getClasses}, should the valuereturned include all parent environments of \code{where}, or thatenvironment only? Defaults to \code{TRUE} if \code{where} isomitted, and to \code{FALSE} otherwise.}\item{validity}{ if supplied, should be a validity-checking methodfor objects from this class (a function that returns \code{TRUE} ifits argument is a valid object of this class and one or more stringsdescribing the failures otherwise). See \code{\link{validObject}}for details. }\item{access}{Access list for the class. Saved in the definition, butnot currently used.}\item{version}{A version indicator for this definition. Saved in thedefinition, but not currently used.}\item{sealed}{ If \code{TRUE}, the class definition will be sealed,so that another call to \code{setClass} will fail on this class name.}\item{package}{ An optional package name for the class. By default(and usually) the package where the class definition is assignedwill be used.}\item{formal}{ Should a formal definition be required? }\item{classDef}{ For \code{removeClass}, the optional classdefinition (but usually it's better for \code{Class} to be theclass definition, and to omit \code{classDef}).}}\details{These are the functions that create and manipulate formal classdefinitions. Brief documentation is provided below. See thereferences for an introduction and for more details.\describe{\item{\code{setClass}:}{Define \code{Class} to be an S-style class. The effect is tocreate an object, of class \code{"classRepEnvironment"}, and storethis (hidden) in the specified environment or database. Objectscan be created from the class (e.g., by calling\code{\link{new}}), manipulated (e.g., by accessing the object'sslots), and methods may be defined including the class name in thesignature (see \code{\link{setMethod}}).}\item{\code{removeClass}:}{Remove the definition of this class, from the environment\code{where} if this argument is supplied; if not,\code{removeClass} will search for a definition, starting in thetop-level environment of the call to \code{removeClass}, andremove the (first) definition found.}\item{\code{isClass}:}{Is this a the name of a formally defined class? (Argument\code{formal} is for compatibility and is ignored.)}\item{\code{getClasses}:}{The names of all the classes formally defined on \code{where}. Ifcalled with no argument, all the classes visible from thecalling function (if called from the top-level, all the classesin any of the environments on the search list). The\code{inherits} argument can be used to search a particularenvironment and all its parents, but usually the default settingis what you want.}\item{\code{findClass}:}{The list of environments or positions on the search list inwhich a class definition of \code{Class} is found. If\code{where} is supplied, this is an environment (ornamespace) from which the search takes place; otherwise thetop-level environment of the caller is used. If \code{unique} is suppliedas a character string, \code{findClass} returns a singleenvironment or position. By default, it always returns alist. The calling function should select, say, the first elementas a position or environment for functions such as\code{\link{get}}.If \code{unique} is supplied as a character string, \code{findClass} willwarn if there is more than one definition visible (using thestring to identify the purpose ofthe call), and will generate an error if no definition can be found.}\item{\code{resetClass}:}{Reset the internal definition of a class. Causes the completedefinition of the class to be re-computed, from therepresentation and superclasses specified in the originalcall to \code{\link{setClass}}.This function is called when aspects of the class definition arechanged. You would need to call it explicitly if you changed thedefinition of a class that this class extends (but doing that inthe middle of a session is living dangerously, since it mayinvalidate existing objects).}\item{sealClass}{ Seal the current definition of the specifiedclass, to prevent further changes. It is possible to seal a classin the call to \code{setClass}, but sometimes further changes haveto be made (e.g., by calls to \code{setIs}). If so, call\code{sealClass} after all the relevant changes have been made.}}}\section{Inheritance and Prototypes}{Defining new classes that inherit from (\dQuote{extend}) other classesis a powerful technique, but has to be used carefully and notover-used. Otherwise, you will often get unintended results when youstart to compute with objects from the new class.As shown in the examples below, the simplest and safest form ofinheritance is to start with an explicit class, with some slots, thatdoes not extend anything else. It only does what we say it does.Then extensions will add some new slots and new behavior.Another variety of extension starts with one of the basic classes,perhaps with the intension of modifying R's standard behavior for thatclass. Perfectly legal and sometimes quite helpful, but you may needto be more careful in this case: your new class will inherit much ofthe behavior of the basic (informally defined) class, and the resultscan be surprising. Just proceed with caution and plenty of testing.As an example, the class \code{"matrix"} is included in thepre-defined classes, to behave essentially as matrices do withoutformal class definitions. Suppose we don't like all of this; inparticular, we want the default matrix to have 0 rows and columns (not1 by 1 as it is now).\code{setClass("myMatrix", "matrix", prototype = matrix(0,0,0))}The arguments above illustrate two short-cuts relevant to suchexamples. We abbreviated the \code{representation} argument to thesingle superclass, because the new class doesn't add anything to therepresentation of class \code{"matrix"}. Also, we provided an objectfrom the superclass as the prototype, not a list of slots.}\references{The R package \pkg{methods} implements, with a few exceptions, theprogramming interface for classes and methods in the book\emph{Programming with Data} (John M. Chambers, Springer, 1998), inparticular sections 1.6, 2.7, 2.8, and chapters 7 and 8.While the programming interface for the \pkg{methods} package followsthe reference, the R software is an original implementation, sodetails in the reference that reflect the S4 implementation may appeardifferently in R. Also, there are extensions to the programminginterface developed more recently than the reference. For adiscussion of details and ongoing development, see the web page\url{http://developer.r-project.org/methodsPackage.html} and thepointers from that page.}\examples{\dontshow{if(isClass("trackMultiCurve"))removeClass("trackMultiCurve")if(isClass("trackCurve"))removeClass("trackCurve")if(isClass("track"))removeClass("track")}## A simple class with two slotssetClass("track",representation(x="numeric", y="numeric"))## A class extending the previous, adding one more slotsetClass("trackCurve",representation("track", smooth = "numeric"))## A class similar to "trackCurve", but with different structure## allowing matrices for the "y" and "smooth" slotssetClass("trackMultiCurve",representation(x="numeric", y="matrix", smooth="matrix"),prototype = list(x=numeric(), y=matrix(0,0,0),smooth= matrix(0,0,0)))#### Suppose we want trackMultiCurve to be like trackCurve when there's## only one column.## First, the wrong way.try(setIs("trackMultiCurve", "trackCurve",test = function(obj) {ncol(slot(obj, "y")) == 1}))## Why didn't that work? You can only override the slots "x", "y",## and "smooth" if you provide an explicit coerce function to correct## any inconsistencies:setIs("trackMultiCurve", "trackCurve",test = function(obj) {ncol(slot(obj, "y")) == 1},coerce = function(obj) {new("trackCurve",x = slot(obj, "x"),y = as.numeric(slot(obj,"y")),smooth = as.numeric(slot(obj, "smooth")))})\dontshow{tMC <- new("trackMultiCurve")is.matrix(slot(tMC, "y"))is.matrix(slot(tMC, "smooth"))setClass("myMatrix", "matrix", prototype = matrix(0,0,0))nrow(new("myMatrix")) # 0nrow(new("matrix")) # 1## simple test of prototype dataxxx <- rnorm(3)setClass("xNum", representation(x = "numeric"), prototype = list(x = xxx))stopifnot(identical(new("xNum")@x, xxx))### tests of the C macros MAKE_CLASS and NEW### FIXME: there should be a separate man page for the C-level macros### and the tests below should be there.stopifnot(identical(.Call("R_methods_test_MAKE_CLASS", "trackCurve", PACKAGE = "methods"),getClass("trackCurve")))stopifnot(identical(.Call("R_methods_test_NEW", "track", PACKAGE = "methods"),new("track")))## The following should not be needed. But make check removes all files## between example files, in a crude way that does not cause the class## information to be reset. There seems no way to detect this, so we## have to remove classes ourselvesremoveClass("withId")removeClass("maybeNumber")removeClass("xNum")removeClass("myMatrix")resetClass("integer")resetClass("numeric")resetClass("logical")removeClass("trackMultiCurve")removeClass("trackCurve")removeClass("track")}}\seealso{\code{\link{setClassUnion}},\code{\link{Methods}},\code{\link{makeClassRepresentation}}}\keyword{programming}\keyword{classes}\keyword{methods}