Rev 19087 | Rev 20620 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
\name{setClass}\alias{setClass}\alias{removeClass}\alias{resetClass}\alias{isClass}\alias{getClasses}\title{Create a Class Definition}\description{Create a formally defined class with specified slots and/orrelationships to other classes. Also functions to remove a classdefinition, to test whether a class has been defined, to test whetheran object is a class definition, and to reset the internal definitionof a class.}\usage{setClass(Class, representation, prototype,contains=character(), validity, access, where=1, version=FALSE)removeClass(Class, where=-1)isClass(Class, formal=TRUE)isClassDef(object)getClasses(where)resetClass(Class)}\arguments{\item{Class}{ character string name for the class }\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}{ What environment to use to store or remove thedefinition (as metadata).By default, uses the global environment for \code{setClass} andsearches for a definition to remove, for \code{removeClass}. }\item{validity, access, version}{ Control arguments included forcompatibility with the S-Plus API, but not currently used. }\item{x}{an arbitrary object.}\item{formal}{ Should a formal definition be required? }\item{object}{ any R object. }}\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. Calling this \emph{always}resets the version of the class cached for the session. If\code{where=0}, that's all it does. Otherwise, it removes theversion from the specified environment or database (from the globalenvironment by default).}\item{\code{isClass}:}{Is this a the name of a formally defined class? (Argument\code{formal} is for compatibility and is ignored.)}\item{\code{isClassDef}:}{Is this object a class definition (it will be, for example, if itis the value of a call to \code{\link{getClass}}, the completedefinition of a class with its extensions, or to\code{\link{getClassDef}}, the local definition of the class).}\item{\code{getClasses}:}{The names of all the classes formally defined on \code{where}. Ifcalled with no argument, all the classes currently known in thesession (which does not include classes that may be defined on oneof the attached packages, but have not yet been used in thesession).}\item{\code{unclass}:}{Returns the object containing the values of all the slots in thisobject's class definition (specifically, if the returned objecthas attributes corresponding to each slot), in the case that theobject's class is formally defined with slots. For classes thatextend a single other class (e.g., a basic class such as\code{"numeric"}) the result is an object of that class.}\item{\code{resetClass}:}{Reset the internal definition of a class. The effect is thatthe next time the definition of this class is needed, it will berecomputed from the information in the currently attached packages.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).}}}\section{Inheritance and Prototypes}{Defining new classes that inherit from (``extend'') other classes is apowerful technique, but has to be used carefully and not over-used.Otherwise, you will often get unintended results when you start tocompute 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 web page \url{http://www.omegahat.org/RSMethods/index.html}is the primary documentation.The functions in this package emulate the facility for classesand methods described in \emph{Programming with Data} (JohnM. Chambers, Springer, 1998). See this book for further details andexamples.}\author{John Chambers}\examples{\testonly{if(isClass("track"))removeClass("track")if(isClass("trackCurve"))removeClass("trackCurve")if(isClass("trackMultiCurve"))removeClass("trackMultiCurve")}## 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")))})\testonly{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))## extending a virtual class with several possible realizations## Used to result in a recursive loop through as()## (in S-Plus 6.0, new() doesn't work right with this class)setClass("maybeNumber")setIs("maybeNumber", "vector") # required to be a data partsetIs("numeric", "maybeNumber")setIs("logical", "maybeNumber")setClass("withId", representation("maybeNumber", id = "character"))ttt <- 1:10 ## relevant that this is class integer, to test indirect extensions##www <- new("withId", ttt, id = "test 1")## The following test should use identical(), but then the two## expressions differ by having the object bit on and off resp.##stopifnot(all(as(www, "maybeNumber") == ttt))## 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")resetClass("integer")resetClass("numeric")resetClass("logical")}}\seealso{\code{\link{Methods}}, \code{\link{setSClass}}}\keyword{programming}\keyword{classes}\keyword{methods}