The following discussion defines methods as implemented in Version 3 of S and described
in the book Statistical Models in S. These methods are supported
in current S for the sake of back compatibility, and this documentation is included
to help understand how such methods work. You should not write new methods in this
form. Method functions are named by concatenating the name of the generic function,
"."
, and the name of a class of S objects; for example, the object
print.category
would be a method for evaluating the function
print
on an object of
class
category
. We say that
print.category
is a matching
method for function
print
and class
category
. Methods are
invoked (from a generic function) in one of three ways: from a call to
UseMethod
in an S function; from internal code invoked through the
.Internal
interface;
or from a call to
NextMethod
contained in another method. When a method
is invoked, a special part of the S evaluator, called the dispatcher is
used. When a function calls
UseMethod
, the dispatcher looks at the class
of an object in the current frame. By default and typically this is the first argument
of the current function. The search begins with the value (as a character vector)
of the
class
attribute of the object. This vector gives the various
classes of objects from which the object inherits properties. In addition, all objects
implicitly inherit from class
default
. Each of the classes in the inheritance
is examined, in order, looking for a method that matches the current function and
that class. The first match obtained causes that method to be evaluated. When the
dispatcher is invoked from a
.Internal
interface the matching mechanism
is the same, with one addition and one exception. The addition is that methods can
be defined and matched for the entire group of functions corresponding to a single
internal interface. For example, all the functions using the
Math
interface
can be matched for class
category
by defining a method
Math.category
.
These functions include
sin
,
abs
, and many others (see
Appendix A of Statistical Models in S for a table of all the groups and
corresponding functions). The exception is that for operators (arithmetic, comparison
and logical) and [potentially] for functions with arbitrary numbers of arguments
like
c
, the dispatcher looks for a single method that consistently matches
all the relevant arguments. More precisely, all the arguments for which there is
a non-default matching method must match to the same method. For example, suppose
there is a method,
Ops.category
, to handle all operators for class
category
.
Then
x+y
will use
Ops.category
if
Ops.category
is the matching method for both
x
and
y
, or if
Ops.category
matches for one of
x
or
y
and there is no matching method
for the other operand. The method code in
Ops.category
is responsible
for knowing which operands had matching methods and (because it is a group method)
for knowing that "+" was the generic function. The special objects
.Method
and
.Generic
provide the needed information (see below). When the dispatcher
is invoked from
NextMethod
, it starts the matching from the position
of the current method in the object's class attribute. Suppose the method
print.category
is being evaluated for an object
thing
with a class attribute as follows:
> class(thing) [1] "ordered" "category" "other"Now we encounter a call to
NextMethod
. The dispatcher will find
the current class,
"category"
, in the inheritance and look next for
a method
print.other
. The two points to keep in mind are: (1) the dispatcher
makes no change to the object's class attribute; and (2) the search for a next method
always starts from the position of the current class. In addition to the arguments,
the following special objects will exist in the frame of the method:
When a method is invoked from the dispatcher, it is evaluated in a frame containing
all the arguments to the generic function. The objects in the frame have their values
as of the time of the call to the method. That is, if changes are made before the
call to
UseMethod
or to
NextMethod
, these changes will
be reflected in the values seen in the new frame. Objects assigned in the frame
other than the arguments are not transmitted to the method.
The class of the object that caused this method to be invoked. This is a character
vector whose elements give the name(s) of the method used. Its primary value is
in methods for operators: here the vector has length 2 (for infix operators) and
its elements are either the name of the method or the empty string. Thus methods
typically use
nchar(.Method[i])
to decide which of the operands belongs
to the relevant class of objects. This is a character vector giving the name of the
group for a group method, or an empty string. This is character string giving the
name of the generic function. Its use is primarily in group methods that need to
know which of the functions in the group they're dealing with.