[R] Method dispatch in S4
Martin Morgan
mtmorgan at fhcrc.org
Thu Aug 8 22:00:19 CEST 2013
On 08/04/2013 02:13 AM, Simon Zehnder wrote:
> So, I found a solution: First in the "initialize" method of class C coerce
> the C object into a B object. Then call the next method in the list with the
> B class object. Now, in the "initialize" method of class B the object is a B
> object and the respective "generateSpec" method is called. Then, in the
> "initialize" method of C the returned object from "callNextMethod" has to be
> written to the C class object in .Object. See the code below.
>
> setMethod("initialize", "C", function(.Object, value) {.Object at c <- value;
> object <- as(.Object, "B"); object <- callNextMethod(object, value);
> as(.Object, "B") <- object; .Object <- generateSpec(.Object);
> return(.Object)})
>
> This setting works. I do not know though, if this setting is the "usual" way
> such things are done in R OOP. Maybe the whole class design is
> disadvantageous. If anyone detects a mistaken design, I am very thankful to
> learn.
Hi Simon -- your 'simple' example is pretty complicated, and I didn't really
follow it in detail! The code is not formatted for easy reading (e.g., lines
spanning no more than 80 columns) and some of it (e.g., generateSpec) might not
be necessary to describe the problem you're having.
A good strategy is to ensure that 'new' called with no arguments works (there
are other solutions, but following this rule has helped me to keep my classes
and methods simple). This is not the case for
new("A")
new("C")
The reason for this strategy has to do with the way inheritance is implemented,
in particular the coercion from derived to super class. Usually it is better to
provide default values for arguments to initialize, and to specify arguments
after a '...'. This means that your initialize methods will respects the
contract set out in ?initialize, in particular the handling of unnamed arguments:
...: data to include in the new object. Named arguments
correspond to slots in the class definition. Unnamed
arguments must be objects from classes that this class
extends.
I might have written initialize,A-method as
setMethod("initialize", "A", function(.Object, ..., value=numeric()){
.Object <- callNextMethod(.Object, ..., a=value)
generateSpec(.Object)
})
Likely in a subsequent iteration I would have ended up with (using the
convention that function names preceded by '.' are not exported)
.A <- setClass("A", representation(a = "numeric", specA = "numeric"))
.generateSpecA <- function(a) {
1 / a
}
A <- function(a=numeric(), ...) {
specA <- .generateSpecA(a)
.A(..., a=a, specA=specA)
}
setMethod(generateSpec, "A", function(object) {
.generateSpecA(object at a)
})
ensuring that A() returns a valid object and avoiding the definition of an
initialize method entirely.
Martin
>
> Best
>
> Simon
>
>
> On Aug 3, 2013, at 9:43 PM, Simon Zehnder <simon.zehnder at googlemail.com>
> wrote:
>
>> setMethod("initialize", "C", function(.Object, value) {.Object at c <- value;
>> .Object <- callNextMethod(.Object, value); .Object <-
>> generateSpec(.Object); return(.Object)})
>
> ______________________________________________ R-help at r-project.org mailing
> list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting
> guide http://www.R-project.org/posting-guide.html and provide commented,
> minimal, self-contained, reproducible code.
>
--
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
More information about the R-help
mailing list