R: Force an Object to Belong to a Class

as {methods} | R Documentation

## Force an Object to Belong to a Class

### Description

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

### Usage

    as(object, Class, coerceFlag=TRUE)

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

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

### Arguments

`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 database on which to store the resulting method for `coerce`; by default, the global environment.

### Summary of Functions

`as`:
  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.

`coerce`:
  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.

`setAs`:
  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`.

### How Functions `as' and `setAs' Work

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 `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.

### The Function `as' Used in Replacements

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.

### Author(s)

John Chambers

### References

The web page 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.

### Examples

    ## 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)new("ca", a=from@b, id = from@id))

    as(CB, "numeric")

[Package Contents]