From mtmorgan at fhcrc.org  Wed Mar 17 01:26:24 2010
From: mtmorgan at fhcrc.org (Martin Morgan)
Date: Tue, 16 Mar 2010 17:26:24 -0700
Subject: [Rd] Problem with S3 to S4 transition
In-Reply-To: <4B9F78E1.6040207@mines-paristech.fr>
References: <4B9F78E1.6040207@mines-paristech.fr>
Message-ID: <4BA021B0.8070808@fhcrc.org>

Hi Renard --

On 03/16/2010 05:26 AM, Renard Didier wrote:
> Hello to everybody
> 
> I am developing a package using R and have the following problem:
> 
> I used to work in a mixture of S3 and S4 mechanism environment: as a
> matter of fact, I used to define my classes (say "DB" for illustration)
> using the setClass function (with representation field), and
> I was using the S3 implicit mechanism writing the functions: print.DB
> and plot.DB.
> 
> Recently, I read some interesting papers on the use of S4 mechanism and
> was convinced that I would have some benefit in turning everything on S4
> formalism.
> This is the reason why I simply renamed my previous functions into
> DB.print and DB.plot (by analogy with other functions where the Class
> name is the leading part of the name). My idea was to use the setMethod
> principle to set the DB.print function as the function for the "print"
> method on the "DB" class.
> Therefore, in the .First.Lib file of my package, I introduced the
> setMethod line just after the setClass one, as in the following example:
> 
>    setClass("DB",
>        representation(flag.grid = "logical", ndim = "numeric",
>        x0 = "numeric", dx = "numeric", nx = "numeric",
>        locators ="character",items = "data.frame"))
>    setMethod("show","DB",function(object) DB.print(object))
>    setMethod("print",signature(x="DB"),function(x,...) DB.print(x))
>    setMethod("plot",signature(x="DB"),function(x,y,...) DB.plot(x))
>    setMethod("["  ,signature(x="DB"),db0.getindex)
>    setMethod("[<-",signature(x="DB"),db0.setindex)
>    setMethod("$"  ,signature(x="DB"),db0.get)
>    setMethod("$<-",signature(x="DB"),db0.set)

'print' is not needed for S4 objects, 'show' does the job.

Normally one does not place setClass() or setMethod() in .First.lib, but
uses them like any other function definition (e.g., in a file
methods-DB.R). It can sometimes be important to use a Collates: field in
the DESCRIPTION file so that classes are defined before methods that
dispatch on them.

> 
> As one can notice, I use the same mechanism for SHOW, PLOT and PRINT.
> Finally I created the package and imagined to use it using library
> statement
> 
> Surprisingly, when I used the library statement, the program tells me:
>> standardGeneric for "print" defined from package "base"
>> standardGeneric for "plot" defined from package "base"
> and creates two objects in the .GlobalEnv, namely "plot" and "print"
> with the following contents:
> 
>> print
> standardGeneric for "print" defined from package "base"
> 
> function (x, ...)
> standardGeneric("print")
> <environment: 0xa275c70>
> Methods may be defined for arguments: x
> Use  showMethods("print")  for currently available ones.
> 
> Nothing similar for "show" although my use of setMethod is the same.
> 
> I see a main difference as "show" belongs to the "methods" library
> whereas the two other belong to the "base" library. Bu t I could not see
> how to avoid a user of my library to have these message and the two
> objects created. 

'show' is already a generic, defined in methods, so a generic does not
need to be created. "plot" is a regular R function, so setMethod("plot",
...) has to create a generic and then associate your method with it.
When setMethod("plot", ...) is defined as suggested above, the new
generic is generated when the package is installed (not loaded, so the
message creating a new generic is only presented at installation) and
placed in the package environment (e.g., ls(name="package:pkgA")) and
not .GlobalEnv. Explicitly calling setGeneric("plot") creates the
generic without the information message.

Consider using a NAMESPACE (and .onLoad() rather than .FirstLib).

Best,

Martin

> I am allowed to set the method as I did (I think that I read something
> telling me that I could not do it with methods of the "base" library).
> Otherwiser how can I define the function DB.print as the required method
> for printing objects belonging to the "DB" class.
> 
> Thank in advance for you help.
> 
> 
> 
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel


-- 
Martin Morgan
Computational Biology / Fred Hutchinson Cancer Research Center
1100 Fairview Ave. N.
PO Box 19024 Seattle, WA 98109

Location: Arnold Building M1 B861
Phone: (206) 667-2793



[Rd] Problem with S3 to S4 transition
Martin Morgan