6

I am trying to get my head around the s3 class system in R.

The documentation says that I need to create a generic function for the method I want to create.

Let's say I want to create a method foo for class XYZ.

With all the packages R has, how can I be sure that I am not overwriting a previously created generic method?

Summary is a bad example since everyone probably knows that it already exists, but there has got to be a chance that my generic could already be defined in a package that I have already loaded or one that I will load.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
Stephen Lien
  • 221
  • 1
  • 2
  • 3
  • 2
    The problem is not in the method, but in class. If your class differs from other packages, the rest becomes trivial. – Roman Luštrik Jul 01 '14 at 07:01
  • The main problem is not overwriting a generic (though this can [result in problems too](https://github.com/lme4/lme4/issues/174)), but masking a non-generic, e.g., `dplyr::filter` (a generic) masks `stats::filter` (a non-generic). Regarding masking *methods* from other package, this can usually be avoided, as it is not difficult to find a class name that is likely to be unique (e.g., who would call a class `merMod` if not the lme4 authors). – Roland Jul 01 '14 at 08:14
  • 2
    Let's take the generic summary and also assume I have no idea that somewhere in R summary is already defined as a generic. If I create summary <- function() usemethod("summary") this will break summary for the GLM object. Is there a way to define a generic so it does not break objects that also might define it. If I define it as summary <- function(x) UseMethod("summary") while it will work for the base case of summary(glm( )) but it now breaks, summary(glm(, dispersion=10)). – Stephen Lien Jul 19 '14 at 20:45
  • You can re-define a function as generic without breaking the original by adding a default method that points to the original. See gist here https://gist.github.com/datalove/88f5a24758b2d8356e32 – Tommy O'Dell Mar 16 '15 at 01:57
  • @RomanLuštrik That’s really only true if your package isn’t attached. As soon as you attach your package, your generic might override other existing functions (or vice versa). It’s definitely a big flaw in R’s package system. – Konrad Rudolph Sep 03 '20 at 18:36

1 Answers1

0

I had experienced similar problems and I would like to post a partial solution here with some lessons learned in this process.

  • I am not sure if the issue is really a S3method overwriting the generic methods, but the non-s3 methods (I had identified some issues with a failure in despatching summary s4 methods in lavaan and semTool package).
  • We can check the available methods by methods("foo") or all methods for the class by methods(class="XYZ").
  • We can check if a generic is already registered by isGeneric("foo").

If the methods are not yet registered, so, we need to set a generic using (not the case for summary):

foo<- function(x) UseMethod("foo")

The 1st problem is:

  1. We are able to see the methods just for loaded packages;
  • There is the option of getS3method(f="foo",class="XYZ") but it requires both function and class;

  • utils::getAnywere("foo") is more broad, but also, just for loaded packages...

This is not really a problem if just S3methods exist (no S4method), and we are not specifying a generic, but just new methods, and we are certain the class name was not yet used.


A 2nd problem is:

  1. If the function has also a S4 method associated, apparently, by specifying new s3 method (even with an already existing generic, as in the case for summary) it messes up the despatch to S4 method
  • For now, the only solution I have seeing is to create a new s3 method for each identified s4 methods...

(i) So we can also track specifically for S3 methods .S3methods("foo") or s3 methods for specific class .S3methods(class="XYZ") and find out specifically the S4 method (using .S4methods("foo") for example) after loading all the main packages I am worried...;

(ii) identifying the object class;

(iii) checking if there are any kind of corresponding method in its documentation (apparently some s4 method is not so easy identifiable in documentation to be easily called inside a s3method)

(iv) if (iii) is not available, assessing its structure; and

(v) specifying corresponding s3 methods for the specific classes by calling the identified method (when available) or extracting the desired output from the object, considering its structure...

(the use of .default is an alternative, but I suppose it needs to be considered carefully).

But although the alternative of respecifying the method considering the class object structure has being somewhat easier for summary methods, for other functions can comprise a really hard work...

I imagine should have a broad solution to contemplate s4 methods automatically, but my limited knowledge on S4methods does not enable to evolve in it for now...

hamagust
  • 728
  • 2
  • 10
  • 28