I try to define a class Ops inheritance on a S3 class that is a list and has a time serie inside the list.
tsnewobject_a <- structure(list(data=ts(1:10,frequency=4,start=2010)),
class="newclass")
tsnewobject_b <- structure(list(data=ts(10:1,frequency=4,start=2010)),
class="newclass")
## Step 1 : with S3 only (note : I don't want to modify Ops.ts)
Ops.newclass <- function(e1,e2) {
if (inherits(e1,"newclass")) e1 <- e1$data
if (inherits(e2,"newclass")) e2 <- e2$data
get(.Generic)(e1,e2)
}
tsnewobject_a+tsnewobject_b
# Qtr1 Qtr2 Qtr3 Qtr4
# 2010 11 11 11 11
# 2011 11 11 11 11
# 2012 11 11
# It works !
tsnewobject_a+1
# Qtr1 Qtr2 Qtr3 Qtr4
# 2010 2 3 4 5
# 2011 6 7 8 9
# 2012 10 11
# It works !
1+tsnewobject_a
# Qtr1 Qtr2 Qtr3 Qtr4
# 2010 2 3 4 5
# 2011 6 7 8 9
# 2012 10 11
# It works !
tsnewobject_a+ts(1:10,frequency=4,start=2010)
# Error in tsnewobject_a + ts(1:10, frequency = 4, start = 2010) :
# non-numeric argument to binary operator
# In addition: Warning message:
# Incompatible methods ("Ops.newclass", "Ops.ts") for "+"
# It doesn't work (it's expected)
ts(1:10,frequency=4,start=2010)+tsnewobject_a
# Error in ts(1:10, frequency = 4, start = 2010) + tsnewobject_a :
# non-numeric argument to binary operator
# In addition: Warning message:
# Incompatible methods ("Ops.ts", "Ops.newclass") for "+"
# It doesn't work (it's expected)
Due to S3 double dispatch, it doesn't work with a simple method. And as I don't want to override Ops.ts (it's for a package) I have to find something.
## Step 2 : setOldClass to complete S3 with a small s4 fix
setOldClass("newclass")
setMethod("Ops",signature = c("newclass","ts"),function(e1,e2) callGeneric(e1$data,e2))
setMethod("Ops",signature = c("ts","newclass"),function(e1,e2) callGeneric(e1,e2$data))
tsnewobject_a+ts(1:10,frequency=4,start=2010)
# Error in tsnewobject_a + ts(1:10, frequency = 4, start = 2010) :
# non-numeric argument to binary operator
# In addition: Warning message:
# Incompatible methods ("Ops.newclass", "Ops.ts") for "+"
# Still doesn't work
ts(1:10,frequency=4,start=2010)+tsnewobject_a
# Error in ts(1:10, frequency = 4, start = 2010) + tsnewobject_a :
# non-numeric argument to binary operator
# In addition: Warning message:
# Incompatible methods ("Ops.ts", "Ops.newclass") for "+"
# Still doesn't work
It seems strange to me, as Ops is a S4 group generic. Shouldn't it call the available S4 methods, then, if there is none, go to S3 ? What happens and how could it be fixed ?