I'd like to have a class A that computes a likelihood, and a subclass B that computes the same likelihood by sometimes throws in an additional term (B includes measurement error). So B's likelihood needs to call A's, and then (sometimes) multiply by an additional term. It sounds as if, in the S3 scheme, NextMethod is supposed to do this: like.A <- function(stuff) compute value like.B <- function(stuff) extraFactor*NextMethod() ? but, after some study of both the Language Manual (2.1) and the online help of NextMethod I can't tell exactly what it does. In particular, I'm not sure if it returns to the calling function, or how it decides which flavor to call. The language manual says the method choice depends on the values of .Generic and .Class, but doesn't say how those get filled in. I would expect .Class to be the current class, in which case the call is recursive. The online help says "'NextMethod' invokes the next method (determined by the class)" but it doesn't say how it is determined. One ambiguity is whether "class" refers to the class (B) or the class attribute ("B", "A"). I think the documentation could be clearer. Now, probably none of this matters to me, since several sources (including the online help for S3)indicate that S4 classes are preferred. I found the documentation for S4 initially elusive. As far as I can tell, it isn't even mentioned in the "R Language Definition." While the fact that S4 is defined in a package makes clear it is not formally part of the base language, this is not a very good way to get people to use S4. I think by now I've tracked down docs on S4, including the intro/overview at http://www.omegahat.org/RSMethods/. Finally, I'm a bit concerned that one article mentioned that S4 inheritance, in practice, is used mostly for data, not methods (Thomas Lumley, R News 4(1), June 2004: p. 36). Am I going down a road I shouldn't travel? -- Ross Boylan wk: (415) 502-4031 530 Parnassus Avenue (Library) rm 115-4 ross at biostat.ucsf.edu Dept of Epidemiology and Biostatistics fax: (415) 476-9856 University of California, San Francisco San Francisco, CA 94143-0840 hm: (415) 550-1062
Gabor Grothendieck
2005-May-23 22:09 UTC
[R] Documentation of S3 and S4 classes, inheritance
On 5/23/05, Ross Boylan <ross at biostat.ucsf.edu> wrote:> I'd like to have a class A that computes a likelihood, and a subclass B > that computes the same likelihood by sometimes throws in an additional > term (B includes measurement error). > > So B's likelihood needs to call A's, and then (sometimes) multiply by an > additional term. > > It sounds as if, in the S3 scheme, NextMethod is supposed to do this: > > like.A <- function(stuff) compute value > like.B <- function(stuff) extraFactor*NextMethod() > ?Here is a working example to try out. In the call to lik, the first class in the class vector is "B" so lik.B gets invoked. The next method of x is "A" so NextMethod invokes lik.A from within lik.B and then returns its result to lik.A which finishes the calculation. lik <- function(x) UseMethod("lik") lik.A <- function(x) mean(x) lik.B <- function(x) NextMethod("lik") + sd(x) x <- structure(1:3, class = c("B", "A")) lik(x) # 3> but, after some study of both the Language Manual (2.1) and the online > help of NextMethod I can't tell exactly what it does. In particular, > I'm not sure if it returns to the calling function, or how it decides > which flavor to call. The language manual says the method choice > depends on the values of .Generic and .Class, but doesn't say how those > get filled in. I would expect .Class to be the current class, in which > case the call is recursive. The online help says "'NextMethod' invokes > the next method (determined by the class)" but it doesn't say how it is > determined. One ambiguity is whether "class" refers to the class (B) or > the class attribute ("B", "A").See above discussion.> > I think the documentation could be clearer. > > Now, probably none of this matters to me, since several sources > (including the online help for S3)indicate that S4 classes are > preferred. > > I found the documentation for S4 initially elusive. As far as I can > tell, it isn't even mentioned in the "R Language Definition." While the > fact that S4 is defined in a package makes clear it is not formally part > of the base language, this is not a very good way to get people to use > S4. > > I think by now I've tracked down docs on S4, including the > intro/overview at http://www.omegahat.org/RSMethods/. > > Finally, I'm a bit concerned that one article mentioned that S4 > inheritance, in practice, is used mostly for data, not methods (Thomas > Lumley, R News 4(1), June 2004: p. 36). Am I going down a road I > shouldn't travel? >This area seems somewhat controversial with different people stating different opinions. IMHO you are probably best off to start with S3 since its simpler and if you do learn S4 later they are not unrelated so it will make it easier than jumping straight into it. Also you may find you never have to go beyond S3 in which case you have saved yourself some time. I personally use S3. By the way if choosing from S3 and S4 is not enough, there are also two CRAN packages that provide additional OO models as well: R.oo and proto.
On Mon, 2005-05-23 at 14:41 -0700, Ross Boylan wrote: ....> Finally, I'm a bit concerned that one article mentioned that S4 > inheritance, in practice, is used mostly for data, not methods (Thomas > Lumley, R News 4(1), June 2004: p. 36). Am I going down a road I > shouldn't travel? >Hmm, maybe I just found out. If B is an S4 subclass of A (aka extends A), how does B's method foo invoke A's foo? The question assumes that A's foo was defined as an in place function, so there's no (obvious) named object for it, i.e, setMethod("A", signature(blah="numeric"), function(x) something)