as                  package:methods                  R Documentation

_F_o_r_c_e _a_n _O_b_j_e_c_t _t_o _B_e_l_o_n_g _t_o _a _C_l_a_s_s

_D_e_s_c_r_i_p_t_i_o_n:

     These functions manage the relations that allow coercing an object
     to a given class.

_U_s_a_g_e:

     as(object, Class, coerceFlag=TRUE)

     as(object, Class, coerceFlag=TRUE) <- value

     setAs(from, to, def, replace, where = 1)

_A_r_g_u_m_e_n_t_s:

  object: Any object. 

   Class: The name of the class to which `object' should be coerced. 

coerceFlag: A logical flag.  If `FALSE',  only inheritance relations
          will be used; i.e., `is(object, Class)' must be `TRUE', and
          if not, `NULL' is returned.

          If the flag is `TRUE', however, coerce methods will be called
          if inheritance is not true (and an error will result if
          coercion fails).

   value: The value to use to modify `object' (see the discussion
          below).  You should supply an object with class `Class'; some
          coercion is done, but you're unwise to rely on it.

from, to: The classes between which `def' performs coercion.

          (In the case of the `coerce' function these are objects from
          the classes, not the names of the classes, but you're not
          expected to call `coerce' directly.)

     def: A function of one argument.  It will get an object from class
          `from' and had better return an object of class `to'. (If you
          want to save `setAs' a little work, make the name of the
          argument `from', but don't worry about it, `setAs' will do
          the conversion.) 

 replace: If supplied, the function to use as a replacement method.

   where: The position or environment in which to store the resulting
          method for `coerce'; by default, the global environment. 

_S_u_m_m_a_r_y _o_f _F_u_n_c_t_i_o_n_s:

     `_a_s': Returns the version of this object coerced to be the given
          `Class'.

          If the corresponding `is' relation is true, it will be used.
          In particular, if the relation has a coerce method, the
          method will be invoked on `object'.

          If the `is' relation is `FALSE', and `coerceFlag' is `TRUE',
          the coerce function will be called (which will throw an error
          if there is no valid way to coerce the two objects). 
          Otherwise, `NULL' is returned.

          Coerce methods are pre-defined for basic classes (including
          all the types of vectors, functions and a few others).  The
          object `asFunctions' contains the list of such pre-defined
          relations: `names(asFunctions)' gives the names of all the
          classes.

          Beyond these two sources of methods, further methods are
          defined by calls to the `setAs' function.


     `_c_o_e_r_c_e': Coerce `from' to be of the same class as `to'.

          Not a function you should usually call explicitly.  The
          function `setAs' creates methods for `coerce' for the `as'
          function to use.


     `_s_e_t_A_s': The function supplied as the third argument is to be
          called to implement `as(x, to)' when `x' has class `from'.
          Need we add that the function should return a suitable object
          with class `to'.

_H_o_w _F_u_n_c_t_i_o_n_s `_a_s' _a_n_d `_s_e_t_A_s' _W_o_r_k:

     The function `as' contrives to turn `object' into an object with
     class `Class'.  In doing so, it uses information about classes and
     methods, but in a somewhat special way.  Keep in mind that objects
     from one class can turn into objects from another class either
     automatically or by an explicit call to the `as' function.
     Automatic conversion is special, and comes from the designer of
     one class of objects asserting that this class extends a another
     class  (see `setClass' and `setIs').

     Because inheritance is a powerful assertion, it should be used
     sparingly (otherwise your computations may produce unexpected, and
     perhaps incorrect, results).  But objects can also be converted
     explicitly, by calling `as', and that conversion is designed to
     use any inheritance information, as well as explicit methods.

     As a first step in conversion, the `as' function determines
     whether `is(object, Class)' is `TRUE'.  This can be the case
     either because the class definition of `object' includes `Class'
     as a ``super class'' (directly or indirectly), or because a call
     to `setIs' established the relationship.

     Either way, the inheritance relation defines a method to coerce
     `object' to `Class'.  In the most common case, the method is just
     to extract from `object' the slots needed for `Class', but it's
     also possible to specify a method explicitly in a `setIs' call.

     So, if inheritance applies, the `as' function calls the
     appropriate method.  If inheritance does not apply, and
     `coerceFlag' is `FALSE', `NULL' is returned.

     By default, `coerceFlag' is `TRUE'.  In this case the `as'
     function goes on to look for a method for the function `coerce'
     for the signature `c(from = class(object), to = Class)'.

     Method selection is used in the `as' function in two special ways.
     First,  inheritance is applied for the argument `from' but not for
     the argument `to' (if you think about it, you'll probably agree
     that you wouldn't want the result to be from some class other than
     the `Class' specified). Second, the function tries to use
     inheritance information to convert the object indirectly, by first
     converting it to an inherited class. It does this by examining the
     classes that the `from' class extends, to see if any of them has
     an explicit conversion method. Suppose class `"by"' does:  Then
     the `as' function implicitly computes `as(as(object, "by"),
     Class)'.

     With this explanation as background, the function `setAs' does a
     fairly obvious computation:  It constructs and sets a method for
     the function `coerce' with signature `c(from, to)', using the
     `def' argument to define the body of the method.  The function
     supplied as `def' can have one argument (interpreted as an object
     to be coerced) or two arguments (the `from' object and the `to'
     class).  Either way, `setAs' constructs a function of two
     arguments, with the second defaulting to the name of the `to'
     class.  The method will be called from `as' with the object as the
     only argument:  The default for the second argument is provided so
     the method can know the intended `to' class.

     The function `coerce' exists almost entirely as a repository for
     such methods, to be selected as desribed above by the `as'
     function. In fact, it would usually be a bad idea to call `coerce'
     directly, since then you would get inheritance on the `to'
     argument; as mentioned, this is not likely to be what you want.

_T_h_e _F_u_n_c_t_i_o_n `_a_s' _U_s_e_d _i_n _R_e_p_l_a_c_e_m_e_n_t_s:

     When `as' appears on the left of an assignment, the intuitive
     meaning is ``Replace the part of `object' that was inherited from
     `Class' by the `value' on the right of the assignment.''

     This usually has a straightforward interpretation, but you can
     control explicitly what happens, and sometimes you should to avoid
     possible corruption of objects.

     When `object' inherits from `Class' in the usual way, by including
     the slots of `Class', the default `as' method is to set the
     corresponding slots in `object' to those in `value'.

     The default computation may be reasonable, but usually only if all
     other slots in `object' are unrelated to the slots being changed. 
     Often, however, this is not the case.  The class of `object' may
     have extended `Class' with a new slot whose value depends on the
     inherited slots.  In this case, you may want to define a method
     for replacing the inherited information that recomputes all the
     dependent information.  Or, you may just want to prohibit
     replacing the inherited information directly .

     The way to control such replacements is through the `replace'
     argument to function `setIs'.  This argument is a method that
     function `as' calls when used for replacement.  It can do whatever
     you like, including calling `stop' if you want to prohibit
     replacements.  It should return a modified object with the same
     class as the `object' argument to `as'.

     In R, you can also explicitly supply a replacement method, even in
     the case that inheritance does not apply, through the `replace'
     argument to `setAs'.  It works essentially the same way, but in
     this case by constructing a method for `"coerce<-"'.  (Replace
     methods for coercion without inheritance are not in the original
     description and so may not be compatible with S-Plus, at least not
     yet.)

     When inheritance does apply, coerce and replace methods can be
     specified through either `setIs' or `setAs'; the effect is
     essentially the same.

_A_u_t_h_o_r(_s):

     John Chambers

_R_e_f_e_r_e_n_c_e_s:

     The web page <URL: http://www.omegahat.org/RSMethods/index.html>
     is the primary documentation.

     The functions in this package emulate the facility for classes and
     methods described in Programming with Data (John M. Chambers,
     Springer, 1998).  See this book for further details and examples.

_E_x_a_m_p_l_e_s:

     ## using the definition of class "track" from Classes



     setAs("track", "numeric", function(from)from@y)

     t1 <- new("track", x=1:20, y=(1:20)^2)

     as(t1, "numeric")

     ## The next example shows:
     ##  1. A virtual class to define setAs for several classes at once.
     ##  2. as() using inherited information

     setClass("ca", representation(a = "character", id = "numeric"))

     setClass("cb", representation(b = "character", id = "numeric"))

     setClass("id")
     setIs("ca", "id")
     setIs("cb", "id")

     setAs("id", "numeric", function(from) from@id)

     CA <- new("ca", a ="A", id = 1)

     CB <- new("cb", b = "B", id = 2)

     setAs("cb", "ca", function(from, to )new(to, a=from@b, id = from@id))

     as(CB, "numeric")

