Defining Object-based Methods in the OOP Package

The definition of an object-based method in the OOP package associates an S function with the method name in the OOP class definition:

track$defineMethod("draw", function() plot(x, y))
Once the method is defined, it can be invoked on any object from the class. If tr1 is an object of class track, then
tr$draw()
will call plot with the arguments shown.

Methods can also be defined to operate only on the class object, by invoking defineClassMethod instead of defineMethod. Both ordinary and class methods can optionally be specified conditional on a signature, that is, on the classes of one or more arguments to the method. See the section on signature methods below.

Writing Method Definitions

The method definition is an S function, which behaves much like ordinary S functions, with a few special features to provide the facilities of OOP programming.
  1. Method Invocation. Inside the body of a method, other methods from this class can be invoked on the current object just by using their name; for example, validate() invokes the validate on this object, with no need to write .this$validate().

  2. Field Access. Similarly, fields in this object can be referenced by name, y evaluates to the field of that name in the current object, if "y" is one of the field names. An alternative is to use field accessor functions (see 4 below).

  3. Modifying Fields. A field can be assigned or modified either by using the field accessor (below), or by the special assignment operator <<-. Note that you can not simply assign the name of the field; by S semantics that would assign a local object of the same name.

  4. Field Accessor Methods The processing of a class definition creates accessor functions to get and set each of the fields. For the field named "y", for example, these would be the methods get.y() and set.y(value), respectively. For most purposes, there is no distinction between the effect of the accessor methods and direct reference to the field. However, if you want to have local variables or arguments with the same name as a field, then to refer to that particular field you must use the accessor functions.

Field Names and Method Argument Names

If the definition of a method has an argument named, say x, the argument name overrides a field of the same name. Inside the method definition, x refers to the argument and not the field, as you presumably would like!

The only catch comes if you want to refer to the field as well. There are several ways, but the preferred solution is to use the field accessor methods, in this case, get.x() to get the field and set.x(value) to assign the field. The distinction arises fairly often in writing initialize methods, since we may want the argument names to be field names, even though we're not just going to assign the fields (if we were, the default initialization method would do that). For example:


track$defineMethod("initialize", function(x = numeric(), y = numeric()) {
      if(missing(y) && !missing(x)) {
          y <- x
          x <- seq(along = y)
      }
      set.x(x)
      set.y(y)
  })

Class Methods

Class methods are defined similarly to ordinary methods, using the defineClassMethod method:


track$defineClassMethod("Something",
  function() {}
)
Class methods are invoked on the class object, not on an object from the class. The most frequently used class method, new, exists to create objects from the class:

t1 <- track$new(x = myX, y = myY)


Last modified: Mon Oct 7 11:20:01 EDT 2002