多个类的 S3 运算符重载

tak*_*kje 5 r operator-overloading r-s3

我定义了两个类,它们可以成功添加两个自己的对象或一个数字和一个自己的对象。

a <- structure(list(val = 1), class = 'customClass1')
b <- structure(list(val = 1), class = 'customClass2')
`+.customClass1` <- function(e1, e2, ...){
  val1 <- ifelse(is.numeric(e1), e1, e1$val)
  val2 <- ifelse(is.numeric(e2), e2, e2$val)
  val_res <- val1  + val2
  print('customClass1')
  return(structure(list(val = val_res), class = 'customClass1'))
}
`+.customClass2` <- function(e1, e2, ...){
  val1 <- ifelse(is.numeric(e1), e1, e1$val)
  val2 <- ifelse(is.numeric(e2), e2, e2$val)
  val_res <- val1  + val2
  print('customClass2')
  return(structure(list(val = val_res), class = 'customClass1'))
}
print.customClass1 <- function(x, ...){
  print(x$val)
}
print.customClass2 <- function(x, ...){
  print(x$val)
}
a + a
# [1] 2
a + 1
# [1] 2
b + b
# [1] 2
1 + b
# [1] 2
Run Code Online (Sandbox Code Playgroud)

但很明显,当我尝试添加两个自定义类时会出错。

a + b
# Error in a + b : non-numeric argument to binary operator
# In addition: Warning message:
# Incompatible methods ("+.customClass1", "+.customClass2") for "+" 
Run Code Online (Sandbox Code Playgroud)

我可以只为 customClass1 定义一个函数,但是当我尝试添加两个 customClass2 对象时,该函数将不起作用。有没有办法让一个功能优先于另一个功能?

R 似乎通过将我的函数优先于基本函数(例如数字或整数类型)来自然地做到这一点。当两个参数之一具有 customClass 类型时,R 会自动将其重定向到我的函数而不是默认函数。

Jos*_*ich 3

R 如何选择要分派的方法将在详细信息部分讨论?base::Ops

\n\n
\n

在调度该组的任何成员时都会考虑这两个参数的类。对于每个参数,检查其类向量以查看是否存在匹配的特定(首选)或“Ops”方法。如果只为一个参数找到一种方法,或者为两个参数找到相同的方法,则使用该方法。如果找到不同的方法,则会出现有关“不兼容方法”的警告:在这种情况下,或者如果没有为任一参数找到方法,则使用内部方法。

\n
\n\n

如果customClass1customClass2相关,则可以使用虚拟类来允许使用两个不同的类进行操作。例如,您可以混合使用POSIXctPOSIXlt因为它们都继承自POSIXt. 这记录在?DateTimeClasses

\n\n
\n

"POSIXct"更方便包含在数据框中,并且更 "POSIXlt"接近人类可读的形式。存在一个虚拟类, "POSIXt"这两个类都继承自该虚拟类:它用于允许诸如减法之类的操作来混合这两个类

\n
\n\n

例如:

\n\n
class(pct <- Sys.time())\n# [1] "POSIXct" "POSIXt"\nSys.sleep(1)\nclass(plt <- as.POSIXlt(Sys.time()))\n# [1] "POSIXlt" "POSIXt"\nplt - pct\n# Time difference of 1.001677 secs\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果这些类不以这种方式相关,那么使用 S3 for \xe2\x80\x9c+\xe2\x80\x9d 方法模拟多重调度的答案中有一些很好的信息 - 可能吗?

\n