`NextMethod()`的内部工作原理

时间:2014-01-05 10:29:11

标签: r oop inheritance methods parametric-polymorphism

我正在试图找出NextMethod()的工作原理。我发现的S3类系统最详细的解释是在钱伯斯和Hastie(编辑)的统计模型在S (1993,Chapman& Hall)中,然而我发现有关NextMethod调用的部分有点模糊。以下是我试图理解的相关段落(第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的 The New S Language ,   第354页)。特别是:

     
      
  • 参数从当前方法传递到继承的方法,并调用它们在NextMethod()时的当前值。
  •   
  • 懒惰评估继续有效;未经评估的论点仍未得到评估。
  •   
  • 继承的方法中缺少缺少的参数。
  •   
  • 通过通过传递的参数“...”正式参数以正确的参数名称到达。
  •   
  • 框架中与调用中的实际参数不对应的对象将不会传递给继承的方法。“
  •   
     

继承过程基本上是透明的   参数go。

我觉得困惑的两点是:

  1. 什么是“当前方法”,什么是“以前的方法”?
  2. “对继承方法的调用中的参数”,“参数的表达式”和“当前方法的相应形式参数的名称”之间有什么区别?
  3. 一般来说,如果有人可以请以萤火虫的方式重述上述段落中的描述,我会很感激。

2 个答案:

答案 0 :(得分:8)

很难通过所有这篇文章,但我认为这个小例子可以帮助神秘化Next Next方法调度。

我创建了一个具有2个类属性(继承)'first'和'second'的对象。

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)

答案 1 :(得分:6)

考虑这个示例,其中调用泛型函数f并调用f.ordered,然后使用NextMethodf.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(评级)已经调用了该方法   print.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