1

假设您尝试使用 S3 模拟双重调度,并且您正在两种方法之间做出选择:

示例 1:一个泛型f()

f <- function(arg1, arg2) UseMethod("f", arg1)
f.foo <- function(arg1, arg2) UseMethod("f.foo", arg2)
f.foo.bar <- function(arg1, arg2) toupper(paste(arg1, arg2))
f.foo.baz <- function(arg1, arg2) tolower(paste(arg1, arg2))

f.faa <- function(arg1, arg2) {
  arg1 <- paste(arg1, arg1)
  NextMethod()
}

f.fee <- function(arg1, arg2){
  x <- NextMethod()
  paste0(x,"!")
}

示例 2:两个泛型g()h()

g <- function(arg1, arg2) UseMethod("g", arg1)
g.foo <- function(arg1, arg2) h(arg2, arg1)
h <- function(arg2, arg1) UseMethod("h", arg2)
h.bar <- function(arg2, arg1) toupper(paste(arg1, arg2))
h.baz <- function(arg2, arg1) tolower(paste(arg1, arg2))

g.faa <- function(arg1, arg2) {
  arg1 <- paste(arg1, arg1)
  NextMethod()
}

g.fee <- function(arg1, arg2){
  x <- NextMethod()
  paste0(x,"!")
}

测试等效性

FOO <- structure("Hello", class = "foo")
FAA <- structure("Greetings", class = c("faa","foo"))
FEE <- structure("Greetings", class = c("fee","foo"))
BAR <- structure("World", class = "bar")
BAZ <- structure("Universe", class = "baz")

#ALL TRUE
identical(f(FOO, BAR), g(FOO, BAR))
identical(f(FOO, BAZ), g(FOO, BAZ))
identical(f(FAA, BAR), g(FAA, BAR))
identical(f(FAA, BAZ), g(FAA, BAZ))
identical(f(FEE, BAR), g(FEE, BAR))
identical(f(FEE, BAZ), g(FEE, BAZ))
  1. 您会说以下哪个示例是更好的选择?
  2. 一个另一个更像双重调度,还是它们本质上是等价的?
  3. 哪个会为用户提供更好的可扩展性/灵活性?

我能说的唯一区别是,在示例 1 中,直接f.foo调用UseMethod("f.foo", arg2),而在示例 2 中,g.foo调用h然后调用UseMethod("h", arg2). 所以简而言之,第二种方法只有一个额外的函数调用。

也许第二个示例在代码结构中更容易跟踪,但它们本质上是等价的。

当然,最终会更好的是类结构和最适合包的 API 的东西

4

0 回答 0