Multiple packages may define methods for the same function, using the
version of a function stored in one package. All these methods should
be marshaled and dispatched consistently when a user calls the
function. For consistency, the generic version of the function must
have a unique definition (the same arguments allowed in methods
signatures, the same values for optional slots such as the value
class, and the same standard or non-standard definition of the
function itself). If the original function is already an S4 generic, there is no
problem. The implicit generic mechanism enforces consistency when the
version in the package owning the function is not generic. If
a call to setGeneric()
attempts to turn a function in
another package into a generic, the mechanism compares the proposed
new generic function to the implicit generic version of that
function. If the two agree, all is well. If not, and if the function
belongs to another package, then the new generic will not be
associated with that package. Instead, a warning is issued and a
separate generic function is created, with its package slot set to the
current package, not the one that owns the non-generic version of the
function. The effect is that the new package can still define methods
for this function, but it will not share the methods in other
packages, since it is forcing a different definition of the generic
function.
The right way to proceed in nearly all cases is to call
setGeneric("foo")
, giving only the name of the
function; this will automatically use the implicit generic version.
If you don't like that version, the best solution is to convince the
owner of the other package to agree with you and to insert code to
define the non-default properties of the function (even if the owner
does not want foo()
to be a generic by default).
For any function, the implicit generic form is a standard generic in
which all formal arguments, except for ...
, are allowed in
the signature of methods. If that is the suitable generic for a
function, no action is needed. If not, the best mechanism is to set up
the generic in the code of the package owning the function, and to
then call setGenericImplicit()
to record the implicit generic
and restore the non-generic version. See the example.
Note that the package can define methods for the implicit generic as
well; when the implicit generic is made a real generic, those methods
will be included.
Other than predefining methods, the usual reason for having a
non-default implicit generic is to provide a non-default signature,
and the usual reason for that is to allow lazy evaluation of
some arguments. See the example. All arguments in the signature of a
generic function must be evaluated at the time the function needs to
select a method. (But those arguments can be missing, with or without
a default expression being defined; you can always examine
missing(x)
even for arguments in the signature.)
If you want to completely prohibit anyone from turning your function
into a generic, call prohibitGeneric()
.