is                  package:methods                  R Documentation

Is an Object from a Class

Description:

     'is': With two arguments, tests whether 'object' can be treated as
     from 'class2'.

     With one argument, returns all the super-classes of this object's
     class.

     'extends': Does the first class extend the second class? Returns
     'maybe' if the extension includes a test.

     'setIs': Defines 'class1' to be an extension of 'class2'.

Usage:

     is(object, class2)

     extends(class1, class2, maybe=TRUE, fullInfo = FALSE)

     setIs(class1, class2, test=NULL, coerce=NULL, replace=NULL,
           by = character(), where = topenv(parent.frame()), classDef =,
           extensionObject = NULL, doComplete = TRUE)

Arguments:

  object: any R object.

class1, class2: the names of the classes between which 'is' relations
          are to be defined.

maybe, fullInfo: In a call to 'extends', 'maybe' is a flag to
          include/exclude conditional relations, and 'fullInfo' is a
          flag, which if 'TRUE' causes object(s) of class
          'classExtension' to be returned, rather than just the names
          of the classes or a logical value.  See the details below.

extensionObject: alternative to the 'test, coerce, replace, by'
          arguments; an object from class 'SClassExtension' describing
          the relation.  (Used in internal calls.) 

doComplete: when 'TRUE', the class definitions will be augmented with
          indirect relations as well.  (Used in internal calls.)

test, coerce, replace: In a call to 'setIs', functions optionally
          supplied to test whether the relation is defined, to coerce
          the object to 'class2', and to alter the object so that
          'is(object, class2)' is identical to 'value'.

      by: In a call to 'setIs', the name of an intermediary class. 
          Coercion will proceed by first coercing to this class and
          from there to the target class.  (The intermediate coercions
          have to be valid.)

   where: In a call to 'setIs', where to store the metadata defining
          the relationship. Default is the global environment.

classDef: Optional class definition for 'class' , required internally
          when 'setIs' is called during the initial definition of the
          class by a call to 'setClass'. _Don't_ use this argument,
          unless you really know why you're doing so.

Details:

     'extends': Given two class names, 'extends' by default says
          whether the first class extends the second; that is, it does
          for class names what 'is' does for an object and a class. 
          Given one class name, it returns all the classes that class
          extends (the 'superclasses' of that class), including the
          class itself.  If the flag 'fullInfo' is 'TRUE', the result
          is a list, each element of which is an object describing the
          relationship; otherwise, and by default, the value returned
          is only the names of the classes.

     'setIs':  This function establishes an inheritance relation
          between two classes, by some means other than having one
          class contain the other.  It should _not_ be used for
          ordinary relationships: either include the second class in
          the 'contains=' argument to 'setClass' if the class is
          contained in the usual way, or consider 'setClassUnion' to
          define a virtual class that is extended by several ordinary
          classes.  A call to 'setIs' makes sense, for example, if one
          class ought to be automatically convertible into a second
          class, but they have different representations, so that the
          conversion must be done by an explicit computation, not just
          be inheriting slots, for example.  In this case, you will
          typically need to provide both a 'coerce=' and 'replace='
          argument to 'setIs'.

          The 'coerce', 'replace', and 'by' arguments behave as
          described for the 'setAs' function.  It's unlikely you would
          use the 'by' argument directly, but it is used in defining
          cached information about classes.  The value returned
          (invisibly) by 'setIs' is the extension information, as a
          list.

          The  'coerce' argument is a function that turns a 'class1'
          object into a 'class2' object.  The 'replace' argument is a
          function of two arguments that modifies a 'class1' object
          (the first argument) to replace the part of it that
          corresponds to 'class2' (supplied as 'value', the second
          argument).  It then returns the modified object as the value
          of the call.  In other words, it acts as a replacement method
          to implement the expression 'as(object, class2) <- value'.

          The easiest way to think of the  'coerce' and 'replace'
          functions is by thinking of the case that  'class1' contains
          'class2' in the usual sense, by including the slots of the
          second class.  (To repeat, in this situation you would not
          call 'setIs', but the analogy shows what happens when you
          do.)

          The 'coerce' function in this case would just make a 'class2'
          object by extracting the corresponding slots from the
          'class1' object. The 'replace' function would replace in the
          'class1' object the slots corresponding to 'class2', and
          return the modified object as its value.

          The relationship can also be conditional, if a function is
          supplied as the 'test' argument.  This should be a function
          of one argument that returns 'TRUE' or 'FALSE' according to
          whether the object supplied satisfies the relation
          'is(object, class2)'. If you worry about such things,
          conditional relations between classes are slightly deprecated
          because they cannot be implemented as efficiently as ordinary
          relations and because they sometimes can lead to confusion
          (in thinking about what methods are dispatched for a
          particular function, for example).  But they can correspond
          to useful distinctions, such as when two classes have the
          same representation, but only one of them obeys certain
          additional constraints.

          Because only global environment information is saved, it
          rarely makes sense to give a value other than the default for
          argument 'where'.  One exception is 'where=0', which modifies
          the cached (i.e., session-scope) information about the class.
           Class completion computations use this version, but don't
          use it yourself unless you are quite sure you know what
          you're doing.

References:

     The R package 'methods' implements, with a few exceptions, the
     programming interface for classes and methods in the book
     _Programming with Data_ (John M. Chambers, Springer, 1998), in
     particular sections 1.6, 2.7, 2.8, and chapters 7 and 8.

     While the programming interface for the 'methods' package follows
     the reference, the R software is an original implementation, so
     details in the reference that reflect the S4 implementation may
     appear differently in R.  Also, there are extensions to the
     programming interface developed more recently than the reference. 
     For a discussion of details see '?Methods' and the links from that
     documentation.

Examples:

     ## a class definition (see setClass for the example)
     setClass("trackCurve",
              representation("track", smooth = "numeric"))
     ## A class similar to "trackCurve", but with different structure
     ## allowing matrices for the "y" and "smooth" slots
     setClass("trackMultiCurve",
              representation(x="numeric", y="matrix", smooth="matrix"),
              prototype = structure(list(), x=numeric(), y=matrix(0,0,0),

                                    smooth= matrix(0,0,0)))
     ## Automatically convert an object from class "trackCurve" into
     ## "trackMultiCurve", by making the y, smooth slots into 1-column matrices
     setIs("trackCurve",
           "trackMultiCurve",
           coerce = function(obj) {
             new("trackMultiCurve",
                 x = obj@x,
                 y = as.matrix(obj@y),
                 curve = as.matrix(obj@smooth))
           },
           replace = function(obj, value) {
             obj@y <- as.matrix(value@y)
             obj@x <- value@x
             obj@smooth <- as.matrix(value@smooth)
             obj})

     ## Automatically convert the other way, but ONLY
     ## if the y data is one variable.
     setIs("trackMultiCurve",
           "trackCurve",
           test = function(obj) {ncol(obj@y) == 1},
           coerce = function(obj) {
             new("trackCurve",
                 x = slot(obj, "x"),
                 y = as.numeric(obj@y),
                 smooth = as.numeric(obj@smooth))
           },
           replace = function(obj, value) {
             obj@y <- matrix(value@y, ncol=1)
             obj@x <- value@x
             obj@smooth <- value@smooth
             obj})

