你可以通过定义来做到这一点+.a
and +.b
作为相同的功能。例如:
a <- "a"
class(a) <- "a"
b <- "b"
class(b) <- "b"
`+.a` <- function(e1, e2){
paste(class(e1), "+", class(e2))
}
`+.b` <- `+.a`
a+a
# [1] "a + a"
a+b
# [1] "a + b"
b+a
# [1] "b + a"
b+b
# [1] "b + b"
# Other operators won't work
a-a
# Error in a - a : non-numeric argument to binary operator
如果你定义Ops.a
and Ops.b
,它还将定义其他运算符的操作,可以通过以下方式访问.Generic
在函数中:
##### Start a new R session so that previous stuff doesn't interfere ####
a <- "a"
class(a) <- "a"
b <- "b"
class(b) <- "b"
Ops.a <- function(e1, e2){
paste(class(e1), .Generic, class(e2))
}
Ops.b <- Ops.a
a+a
# [1] "a + a"
a+b
# [1] "a + b"
b+a
# [1] "b + a"
b+b
# [1] "b + b"
# Ops covers other operators besides +
a-a
# [1] "a - a"
a*b
# [1] "a * b"
b/b
# [1] "b / b"
Update: 我在玩这个的时候还发现了一件事。如果将其放入包中,您将收到“非数字参数”错误和“不兼容的运算符”警告。这是因为,只有当多个运算符是完全相同的对象、在内存中具有相同的地址时,R 才可以使用多个运算符——但不知何故,在构建和加载包时,这两个函数会失去这个确切的标识。 (您可以通过使用来检查这一点pryr::address()
)
我发现有效的一件事是在加载包时显式注册 S3 方法。例如,这将放入您的包中:
# Shows the classes of the two objects that are passed in
showclasses <- function(e1, e2) {
paste(class(e1), "+", class(e2))
}
.onLoad <- function(libname, pkgname) {
registerS3method("+", "a", showclasses)
registerS3method("+", "b", showclasses)
}
在这种情况下,这两个方法指向内存中完全相同的对象,并且它可以工作(尽管它有点像黑客)。