Skip to content

exporting s3 and s4 methods

6 messages · John Chambers, Thomas Lumley

#
If a package defined an S3 generic and an S4 generic for the same function (so as to add methods for S4 classes to the existing code), how do I set up the namespace to have them exported?

With 
import(stats)
exportMethods(bigglm)
importClassesFrom(DBI)
useDynLib(biglm)
export(biglm)
export(bigglm)
in NAMESPACE, the S3 generic is not exported.
[1] bigglm.RODBC*      bigglm.data.frame* bigglm.function*

    Non-visible functions are asterisked
Warning messages:
1: In findGeneric(generic.function, parent.frame()) :
   'bigglm' is a formal generic function; S3 methods will not likely be found
2: In methods("bigglm") : function 'bigglm' appears not to be generic


[This is R 2.7.2, admittedly a little ancient]

       -thomas

Thomas Lumley			Assoc. Professor, Biostatistics
tlumley at u.washington.edu	University of Washington, Seattle
#
You shouldn't have to export the S3 function:  in the normal practice, 
setGeneric("biglm") or just a setMethod("biglm", ....) will cause the S3 
function (like any existing function) to become the default method for 
the S4 generic.  There is only one object called "biglm".

It's important though to use the default, one argument, call to 
setGeneric().  Otherwise the two functions are not consistent and can't 
exist in the same namespace.  Also, the situation is different if the S3 
function is in another package, as discussed in a previous thread here 
recently.

The warning messages below, if they are still current, are misleading, 
and usually outright wrong.  The code should look at the default method 
for the S4 generic.

John

PS: if this is the biglm() in the biglm package, the current CRAN 
version is not a generic of any flavor.  Presumably this is a new 
version?  Just curious, this has no effect on the above comments.
Thomas Lumley wrote:
#
On Tue, 17 Mar 2009, John Chambers wrote:

            
Thanks. Does this include restricting which arguments are used for dispatch? I have
  setGeneric("bigglm", signature=c("formula","data"))
to dispatch just on the first two arguments.

I will try to run everything on my desktop back in Seattle to see if there are still problems under r-devel -- my laptop is staying with its current version of R until my book goes to the publisher.
You're missing a 'g'. It's bigglm(), which is S3-generic already.  The current version uses S3 inheritance on SQLiteConnection (which works, but doesn't extend to other DBIConnection objects, as you pointed out previously).


       -thomas

Thomas Lumley			Assoc. Professor, Biostatistics
tlumley at u.washington.edu	University of Washington, Seattle
#
Thomas Lumley wrote:
That seems not to disturb anything. (It's really only the arguments 
affecting the default that would break things directly. The other 
non-defaults are a problem if multiple packages turn the same S3 
function into a generic in inconsistent ways. But here you own both the 
S3 and S4 versions.)

(R2.8.1)> foo <- function(x,y,z)UseMethod("foo")
(R2.8.1)> setGeneric("foo", signature = c("x", "y"))
[1] "foo"
(R2.8.1)> getMethod(foo) # the default
Method Definition (Class ?derivedDefaultMethod?):

function (x, y, z)
UseMethod("foo")

Signatures:

target
defined
(R2.8.1)> foo at signature
[1] "x" "y"
#
I'm still having problems getting a package to define both S3 and S4 methods for the same new generic, on a current r-devel (version 48144).

Symptoms
bigglm> data(trees)

bigglm> ff<-log(Volume)~log(Girth)+log(Height)

bigglm> a <- bigglm(ff,data=trees, chunksize=10, sandwich=TRUE)
Error in UseMethod("bigglm", data) : no applicable method for "bigglm"
Function: bigglm (package biglm)
formula="ANY", data="ANY"
formula="ANY", data="DBIConnection"
formula="formula", data="data.frame"
     (inherited from: formula="ANY", data="ANY")
standardGeneric for "bigglm" defined from package "biglm"

function (formula, data, family = gaussian(), ...) 
standardGeneric("bigglm")
<environment: 0x8554240>
Methods may be defined for arguments: formula, data
Use  showMethods("bigglm")  for currently available ones.
Method Definition (Class "derivedDefaultMethod"):

function (formula, data, family = gaussian(), ...) 
UseMethod("bigglm", data)
<environment: namespace:biglm>

Signatures:
         formula data 
target  "ANY"   "ANY"
defined "ANY"   "ANY"
[1] bigglm.data.frame* bigglm.function*   bigglm.RODBC*

    Non-visible functions are asterisked
Warning messages:
1: In findGeneric(generic.function, parent.frame()) :
   'bigglm' is a formal generic function; S3 methods will not likely be found
2: In methods("bigglm") : function 'bigglm' appears not to be generic

In the NAMESPACE file I have
import(stats)
useDynLib(biglm)
importClassesFrom(DBI)
exportMethods(bigglm)
export(biglm)
export(bigglm)
S3method(bigglm,data.frame)
S3method(bigglm,"function")
S3method(bigglm, RODBC)

and in the code
bigglm<-function(formula, data, family=gaussian(),...)
     UseMethod("bigglm", data)
setGeneric("bigglm", signature=c("formula","data"))


bigglm.data.frame<-function(formula, data, ..., chunksize=5000){ <snip>

setMethod("bigglm",
            c("ANY","DBIConnection"),
            function(formula, data, family = gaussian(),
                                    tablename, ..., chunksize=5000){
              terms<-terms(formula)
              modelvars<-all.vars(formula)
      <snip>


Any suggestions?

     -thomas

Thomas Lumley			Assoc. Professor, Biostatistics
tlumley at u.washington.edu	University of Washington, Seattle
#
Could you send me your package code, off-list.  I think the problem may 
be related to non-exported S3 method objects.

John
Thomas Lumley wrote: