为什么方法继承会杀死额外的参数?

Why does method inheritance kill additional arguments?

我想在我的泛型中设置一些标志(调用UseMethod()之前,我知道很多:)),然后使用and/or更新方法中的这些标志。

像这样:

g <- function(x) {
  y <- 10
  UseMethod("g")
}
g.default <- function(x) {
  c(x = x, y = y)
}
g.a <- function(x) {
  y <- 5  # update y from generic here
  NextMethod()
}

这在直接跳转到默认方法时有效:

g(structure(.Data = 1, class = "c"))  # here y is never updated
# x  y 
# 1 10 

但是当我通过NextMethod()时,y神秘地消失了:

g(structure(.Data = 1, class = "a"))  # here y is updated, but cannot be found
# Error in g.default(structure(.Data = 1, class = "a")) : 
#  object 'y' not found

已经想出了解决这个问题的方法,只是绕过 y 很多:

f <- function(x, ...) {
  y <- 10
  UseMethod("f")
}
f.default <- function(x, ..., y = 3) {
  c(x = x, y = y)
}
f.a <- function(x, ...) {
  y <- 5
  NextMethod(y = y)
}

产生

f(structure(.Data = 1, class = "c"))
# x y 
# 1 3 
f(structure(.Data = 1, class = "a"))
# x y 
# 1 5 

我的问题是:为什么在上面的g().*-example中NextMethod()杀死了额外的y参数?

我认为 UseMethod()NextMethod() 的重点是在调用之间传递任何和所有对象,无需 手动传递他们在:

NextMethod works by creating a special call frame for the next method. If no new arguments are supplied, the arguments will be the same in number, order and name as those to the current method but their values will be promises to evaluate their name in the current method and environment.

我特别困惑的是,UseMethod() 似乎会在 y 上传递,但 NextMethod() 不会。

正如@Roland 指出的那样,这种行为已记录在案:

来自 help("UseMethod") 关于 UseMethod() 注释的段落(强调已添加):

UseMethod creates a new function call with arguments matched as they came in to the generic. Any local variables defined before the call to UseMethod are retained (unlike S). Any statements after the call to UseMethod will not be evaluated as UseMethod does not return.

有关 NextMethod() 的相应段落(已在上面引用)仅注释:

NextMethod works by creating a special call frame for the next method. If no new arguments are supplied, the arguments will be the same in number, order and name as those to the current method but their values will be promises to evaluate their name in the current method and environment. Any named arguments matched to … are handled specially: they either replace existing arguments of the same name or are appended to the argument list. They are passed on as the promise that was supplied as an argument to the current environment. (S does this differently!) If they have been evaluated in the current (or a previous environment) they remain evaluated. (This is a complex area, and subject to change: see the draft ‘R Language Definition’.)

简而言之,UseMethod() 做了一些特别的事情:它传递局部变量NextMethod(),像往常一样,不这样做。

UseMethod() 是例外,而不是 NextMethod().