Peter Ruckdeschel
2006-Apr-12 11:27 UTC
[Rd] yet another problem with S4 dispatch (with setClassUnion)
Dear John and Seth, dear R-devels, once again the question of method dispatch in S4 -- this time with setClassUnion(); taking up your advice in https://stat.ethz.ch/pipermail/r-devel/2006-April/037200.html https://stat.ethz.ch/pipermail/r-devel/2006-April/037201.html I have been too quick in stating that>setClassUnion()---at least in my case---solves the problem; >The problem arises if I have a direct superclass "competing" with the new class generated by setClassUnion(); consider the following code: ## C00 mother class to C01 and C02 setClass("C00", representation(a="numeric"), prototype =c(a=0)) setClass("C01", representation(a="numeric",b="numeric"), contains= "C00") setClass("C02", representation(a="numeric",d="numeric"), contains= "C00") #with setClassUnion: setClassUnion("C01OrC02", c("C01","C02")) # "+" methods for C00 and C01OrC02 # that this is a function to be dispatched on two arguments is # not important for this example setMethod("+", signature=c("C00","C00"), function(e1,e2){e1 at a+e2@a}) setMethod("+", signature=c("C01OrC02","C01OrC02"), function(e1,e2){if(is(e1,"C01")) e10 <- e1 # else: explicit coercion from C02 to C01 else e10 <- new("C01", a=e1 at a, b=e1 at d) if(is(e2,"C01")) e20 <- e2 # else: explicit coercion from C02 to C01 else e20 <- new("C01", a=e2 at a, b=e2 at d) e10 at b+e20@b}) x1=new("C02", a=1, d=2) x2=new("C02", a=1, d=3) x1+x2 ## 2, i.e. uses C00-method # but I would like to force usage of C01OrC02-method Here the two classes C00 and C01OrC02 are direct superclasses to C02, which exactly reflects my application of distribution classes, confer https://stat.ethz.ch/pipermail/r-devel/2006-April/037190.html How does the dispatching mechanism decide between these two and is there a way to change precedence? Of course, I could implement a "+" method for C02 directly in this case, but suppose I have much more methods for C01 and I want to use /all/ of them for C02, and cannot organize things so that we have the inheritance chain C00 -> C01 -> C02. What is the preferred way of doing this? Thank you already for your attention, Peter
John Chambers
2006-Apr-12 13:20 UTC
[Rd] yet another problem with S4 dispatch (with setClassUnion)
As I think Seth told you before, if you want to control the order of inheritance at the same level, you need to use the intended order in the contains= argument to setClass. In your example (retaining the class union, although it's not required, the superclass could just be an ordinary virtual class), setClassUnion("C01OrC02") ## C00 mother class to C01 and C02 setClass("C00", representation(a="numeric"), prototype =c(a=0)) setClass("C01", representation(a="numeric",b="numeric"), contains= c("C01OrC02", "C00")) setClass("C02", representation(a="numeric",d="numeric"), contains= c("C01OrC02", "C00")) seems to give what you want. > x1 + x2 [1] 5 > extends("C01") [1] "C01" "C01OrC02" "C00" To answer one of your other questions, the point about inheritance asserting substitutability is that you now need to be sure that EVERY method for C01OrC02 is preferred to a method for C00 for the new subclasses. As a general design point, having these competing superclasses is likely to confuse the user, if not the implementer. If you could, it would make a clearer picture to have, e.g., C01orC02 be a subclass of C00. Then the inheritance is obvious--C01or... is a parent, while C00 is a grandparent. The special contains= then doesn't need to be repeated for every subclass Cx. Peter Ruckdeschel wrote:>Dear John and Seth, dear R-devels, > >once again the question of method dispatch in S4 -- this time with >setClassUnion(); taking up your advice in > >https://stat.ethz.ch/pipermail/r-devel/2006-April/037200.html >https://stat.ethz.ch/pipermail/r-devel/2006-April/037201.html > >I have been too quick in stating that > > > >>setClassUnion()---at least in my case---solves the problem; >> >> >> >The problem arises if I have a direct superclass "competing" >with the new class generated by setClassUnion(); > >consider the following code: > >## C00 mother class to C01 and C02 >setClass("C00", representation(a="numeric"), prototype =c(a=0)) >setClass("C01", representation(a="numeric",b="numeric"), contains= "C00") >setClass("C02", representation(a="numeric",d="numeric"), contains= "C00") > >#with setClassUnion: >setClassUnion("C01OrC02", c("C01","C02")) > ># "+" methods for C00 and C01OrC02 ># that this is a function to be dispatched on two arguments is ># not important for this example > >setMethod("+", signature=c("C00","C00"), function(e1,e2){e1@a+e2@a}) >setMethod("+", signature=c("C01OrC02","C01OrC02"), > function(e1,e2){if(is(e1,"C01")) e10 <- e1 > # else: explicit coercion from C02 to C01 > else e10 <- new("C01", a=e1@a, b=e1@d) > if(is(e2,"C01")) e20 <- e2 > # else: explicit coercion from C02 to C01 > else e20 <- new("C01", a=e2@a, b=e2@d) > e10@b+e20@b}) > >x1=new("C02", a=1, d=2) >x2=new("C02", a=1, d=3) > >x1+x2 ## 2, i.e. uses C00-method ># but I would like to force usage of C01OrC02-method > >Here the two classes C00 and C01OrC02 are direct superclasses to >C02, which exactly reflects my application of distribution classes, >confer https://stat.ethz.ch/pipermail/r-devel/2006-April/037190.html > >How does the dispatching mechanism decide between >these two and is there a way to change precedence? > >Of course, I could implement a "+" method for C02 directly >in this case, but suppose I have much more methods for >C01 and I want to use /all/ of them for C02, and cannot >organize things so that we have the inheritance chain >C00 -> C01 -> C02. What is the preferred way of doing >this? > >Thank you already for your attention, >Peter > >______________________________________________ >R-devel@r-project.org mailing list >https://stat.ethz.ch/mailman/listinfo/r-devel > > >[[alternative HTML version deleted]]