It's a bug resulting from the combination of: 1. multiple recursive levels of callNextMethod() 2. nonstandard arguments in the method definition; that is, (.Object, x) vs .Object, ...) for the generic.
Specifically, the callNextMethod code tries to build up a list of "excluded" classes, but in this example seems to fail. So the nextMethod selected for class "B", when it goes to find the next^2 method, forgets to exclude class "C"; hence it goes back to the "C" method & so infinite recursion. To see what's happening, use trace(callNextMethod, recover) or equivalent. The computation in addNextMethod, callNextMethod, etc. is all very heuristic (aka "kludgey") code, so it's not clear how easy a fix would be. The desirable route would be a better treatment of nonstandard arguments, but that may require digging deeper into the R evaluator than I've had the nerve to do so far. Meanwhile, a work around is to avoid mechanism 2 if you want to use mechanism 1. This may require separating out the guts of each method from the callNextMethod() part, with that part coming in a method definiton with standard arguments. With the alternative definition below, all is well (if not very useful): > new("C", a=1,b=2,c=3) in C in B in A An object of class "C" Slot "c": [1] 3 Slot "b": [1] 2 Slot "a": [1] 1 using the methods: setMethod("initialize", signature(.Object="A"), function(.Object, ...) { cat("in A\n") callNextMethod() }) setMethod("initialize", signature(.Object="B"), function(.Object, ...) { cat("in B\n") callNextMethod() }) setMethod("initialize", signature(.Object="C"), function(.Object, ...) { cat("in C\n") callNextMethod() }) Seth Falcon wrote: >Hi, > >Given a simple three class hierarchy: A <-- B <-- C > >I want to define an initialize method for each class such that when I >call new("C", x=5), the initialize methods for A and B are used to >incrementally build the object. > >When I do what seems obvious to me using callNextMethod, I get an >infinite recursion. An example follows... > >setClass("A", representation(a="numeric")) >setClass("B", representation(b="numeric"), contains="A") >setClass("C", representation(c="numeric"), contains="B") > >setMethod("initialize", signature(.Object="A"), > function(.Object, x) { > cat("in A\n") > [EMAIL PROTECTED] <- x > .Object > }) > >setMethod("initialize", signature(.Object="B"), > function(.Object, x) { > cat("in B\n") > .Object <- callNextMethod(.Object=.Object, x=x) > [EMAIL PROTECTED] <- [EMAIL PROTECTED] + 1 > .Object > }) > >setMethod("initialize", signature(.Object="C"), > function(.Object, x) { > cat("in C\n") > .Object <- callNextMethod(.Object=.Object, x=x) > [EMAIL PROTECTED] <- [EMAIL PROTECTED] + [EMAIL PROTECTED] + 1 > .Object > }) > > >## Works as I am expecting for B > > >>myB <- new("B", 4) >> >> >in B >in A > >## When you create a C, the B method gets called but the appropriate >## next method info seems lost and we end up back in C's method ?! > > >>myC <- new("C", 5) >> >> >in C >in B >in C >in B >in C > C-c C-c > >Should this work? Is there a better way to organize the initializers >for a simple hierarchy (perhaps assume that args to the initializers >are not the same for A, B, and C). > >Thanks, > >+ seth > >______________________________________________ >R-devel@r-project.org mailing list >https://stat.ethz.ch/mailman/listinfo/r-devel > > > [[alternative HTML version deleted]] ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel