`NextMethod()` 的内部工作原理
Posted
技术标签:
【中文标题】`NextMethod()` 的内部工作原理【英文标题】:The inner workings of `NextMethod()` 【发布时间】:2014-01-22 19:48:32 【问题描述】:我试图弄清楚NextMethod()
的工作原理。我在 Chambers & Hastie (edts.) 的 Statistical Models in S (1993, Chapman & Hall) 中找到了关于 S3 类系统的最详细解释,但我发现有关 @987654322 的部分@ 调用有点晦涩。以下是我试图理解的相关段落(第 268-269 页)。
现在转向作为调用结果调用的方法
NextMethod()
,它们的行为就像是从 以前的方法有一个特殊的调用。调用中的参数 继承的方法在数量、顺序和实参上都相同 名称与调用当前方法中的名称相同(因此,在 对泛型的调用)。然而,参数的表达式, 是当前的相应形式参数的名称 方法。例如,假设表达式print(ratings)
具有 调用了方法print.ordered()
。当此方法调用NextMethod()
,这相当于调用print.factor()
print.factor(x)
的形式,其中x
在这里是框架中的x
print.ordered()
。如果多个参数与形式参数匹配 “...
”,这些参数在对继承的调用中表示 方法 y 特殊名称“..1
”、“..2
”等。评估者认可 这些名称并适当地对待它们(参见第 476 页的 示例)。存在这个相当微妙的定义是为了确保 S 中的函数调用尽可能干净地传递给 方法(比较 Becker、Chambers 和 Wilks 的新 S 语言, 第 354 页)。特别是:
在调用NextMethod()
时,参数会以其当前值从当前方法传递到继承的方法。 延迟评估继续有效;未评估的参数保持未评估。 继承的方法中仍然缺少缺少的参数。 通过“...
”形式参数传递的参数以正确的参数名称到达。 框架中与调用中的实际参数不对应的对象将不会传递给继承的方法。"继承过程基本上是透明的 论据去。
我感到困惑的两点是:
-
什么是“当前方法”,什么是“以前的方法”?
“对继承方法的调用中的参数”、“参数的表达式”和“当前方法的相应形式参数的名称”有什么区别?
一般来说,如果有人能以清晰的方式重述上述段落中的描述,我将不胜感激。
【问题讨论】:
【参考方案1】:很难看完所有这篇文章,但我认为这个小例子可以帮助揭开NextMethod
调度的神秘面纱。
我创建了一个具有 2 个类属性(继承)“第一”和“第二”的对象。
x <- 1
attr(x,'class') <- c('first','second')
然后我创建一个generic
方法Cat
来打印我的对象
Cate <- function(x,...)UseMethod('Cate')
我为每个类定义了Cate
方法。
Cate.first <- function(x,...)
print(match.call())
print(paste('first:',x))
print('---------------------')
NextMethod() ## This will call Cate.second
Cate.second <- function(x,y)
print(match.call())
print(paste('second:',x,y))
现在您可以使用此示例检查Cate
呼叫:
Cate(x,1:3)
Cate.first(x = x, 1:3)
[1] "first: 1"
[1] "---------------------"
Cate.second(x = x, y = 1:3)
[1] "second: 1 1" "second: 1 2" "second: 1 3"
对于 Cate.second,之前的方法是 Cate.first
参数 x 和 y 从当前方法传递到继承的
方法及其在调用 NextMethod() 时的当前值。
通过“...”形式参数传递的参数 y 以正确的参数名称到达 Cate.second(x = x, y = 1:3)
【讨论】:
【参考方案2】:考虑这个例子,其中泛型函数f
被调用并调用f.ordered
,然后使用NextMethod
,f.ordered
调用f.factor
:
f <- function(x) UseMethod("f") # generic
f.ordered <- function(x) x <- x[-1]; NextMethod()
f.factor <- function(x) x # inherited method
x <- ordered(c("a", "b", "c"))
class(x)
## [1] "ordered" "factor"
f(x)
## [1] b c
## Levels: a < b < c
现在考虑原文:
现在转到由于调用 NextMethod() 而调用的方法, 这些行为就好像它们是从以前的方法中调用的一样 一个特殊的电话。
这里 f
调用 f.ordered
调用 f.factor
所以方法“调用为
调用 NextMethod 的结果是 f.factor
,前一个方法是
f.ordered
.
对继承方法的调用中的参数在 数字、顺序和实际参数名称与调用 当前方法(因此,在对泛型的调用中)。这 然而,参数的表达式是 当前方法的相应形式参数。假设,对于 例如,表达式 print(ratings) 调用了该方法 打印.ordered()。当此方法调用 NextMethod() 时,这是 相当于以 print.factor(x) 形式调用 print.factor(), 其中 x 是 print.ordered() 框架中的 x
现在我们切换视角,我们坐在f.ordered
所以现在f.ordered
是当前方法,f.factor
是继承方法。
在f.ordered
调用NextMethod()
时,构造了一个特殊调用
调用f.factor
,其参数与传递给f.ordered
的参数相同,并且
到通用f
除了它们引用 f.ordered
中的参数版本(其中
在这里有所不同,因为f.ordered
在调用之前更改了参数
f.factor
。
【讨论】:
以上是关于`NextMethod()` 的内部工作原理的主要内容,如果未能解决你的问题,请参考以下文章