[Rd] S4 method implementation for S3 class

Iñaki Úcar
Fri, 22 Sep 2017 17:28:05 -0000

2017-09-22 19:04 GMT+02:00 Michael Lawrence <lawrence.michael at
gene.com>:
> The %*% function is a primitive. As it says in the documentation under
> ?Methods_Details
>
>      Methods may be defined for most primitives, and corresponding
>      metadata objects will be created to store them. Calls to the
>      primitive still go directly to the C code, which will sometimes
>      check for applicable methods. The definition of ?sometimes? is
>      that methods must have been detected for the function in some
>      package loaded in the session and ?isS4(x)? is ?TRUE? for the
>      first argument (or for the second argument, in the case of binary
>      operators).
>
> But:
>> isS4(x)
> [1] FALSE
>
> I think this behavior is in the interest of performance. It avoids
> adding S4 dispatch overhead to e.g. matrix objects.

I see, thanks for the explanation.

> In general, it's best to define an S4 class when using S4 dispatch,
> but it sounds like you're stuck using some legacy S3 objects. In that
> case, one would normally define an S3 method for `%*%()` that
> delegates to a custom non-primitive generic, perhaps "matmult" in
this
> case. But since %*% is not an S3 generic, that's not an option.
>
> It would help to hear more about the context of the problem.

This is a problem that Edzer Pebesma and I are facing in our packages
units and errors respectively (you can find both on CRAN). They are
designed in a similar way: units or errors are attached to numeric
vectors as an attribute of an S3 class, and Ops, Math and Summary are
redefined to cope with such units/errors.

Then Edzer found that the %*% operator silently drops the attributes,
so we were trying, without success, to set a method for our respective
S3 classes to at least show a warning stating that the units/errors
are being dropped.

Ours are perfect use cases for S3 classes, and it would be a pitty if
we have to switch everything to S4 just to show a warning. Clearly
overkilling. Isn't there another way?

I?aki