Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
226 views
in Technique[技术] by (71.8m points)

r - Using S4 dispatch for `+` on objects extending multiple S3 classes

I am trying to extend an existing S3 object to S4 in order to have better control over dispatch with the + operator. In the base case, e1 and e2 will typically inherit from the same class, but the goal is to have the dispatch call the S4 method. The code below is my attempt to show the error.

Suppose we have two S3 classes a and b with their own + methods.

a <- function(x) structure(x, class = "a")
"+.a" <- function(e1, e2) cat("+.a method
")
a(1) + 1
#+.a method
b <- function(x) structure(x, class = "b")
"+.b" <- function(e1, e2) cat("+.b method
")
b(1) + 1
#+.a method

These two classes cannot be added together because they have no shared classes with a + method defined

a(1)+b("")
#Error in a(1) + b("") : non-numeric argument to binary operator
#In addition: Warning message:
#Incompatible methods ("+.a", "+.b") for "+"

So, my next step was to see if I could solve this issue in S4. I begin by setting old S3 classes and creating a new S4 to extend on.

setOldClass("a")
setOldClass("b")
setClass("B", contains = c("b","a"))

Now to test S4 with a + method:

setMethod("+", signature("B", "a"), function(e1,e2) cat("B,a S4 Method"))

new("B") + 1
#+.b method  #expected to default to +.b as no S4 signature defined for "B","numeric"
new("B") + a(1)
#B,a S4 Method  #Also expected result
new("B") + new("B")
#B,a S4 Method  #Also expected result

Everything works as expected so far. The unexpected dispatch calls (in my opinion) occur when the S3 objects have multiple inheritance.

ab <- structure(1, class = c("a", "b"))
ba <- structure(1, class = c("b", "a"))
ca <- structure(1, class = c("c", "a"))
cab <- structure(1, class = c("c", "a", "b"))
new("B") + ab
#B,a S4 Method
new("B") + ba
#+.b method
new("B") + ca
#Error in new("B") + ca : non-numeric argument to binary operator
#In addition: Warning message:
#Incompatible methods ("+.b", "+.a") for "+" 
new("B") + cab
#Error in new("B") + cab : non-numeric argument to binary operator
#In addition: Warning message:
#Incompatible methods ("+.b", "+.a") for "+"

I would have expected the S4 dispatch to check signatures in the following manner:

signature("B","c") # Failed: no method
signature("B","a") # Method Exists

Instead it seems to be checking like so:

signature("B", "c") # Failed: no method
signature("b", "a") # Methods Exists --- But they are incompatible

I know I could make a method for a signature("B","c") but the issue with this is that I may not know what new class may exist on e2, which is why I want to dispatch on a shared class of a because all objects will inherit from this class, S4 or S3.

question from:https://stackoverflow.com/questions/65833399/using-s4-dispatch-for-on-objects-extending-multiple-s3-classes

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...