混合S3和S4时的方法分派

我想了解在混合使用S3和S4时R经过的步骤以找到合适的功能。这是一个示例:

set.seed(1)
d <- data.frame(a=rep(c('a','b'),each=15),b=rep(c('x','y','z'),times=5),y=rnorm(30))

m <- lme4::lmer(y ~ b + (1|a),data=d)
l <- lsmeans::lsmeans(m,'b')
multcomp::cld(l)

我不完全了解执行最后一行时会发生什么。

multcomp::cld打印UseMethod("cld"),因此S3方法分派。

isS4(l)显示l是S4类对象。

似乎,尽管调用了S3泛型,但S3调度系统却被完全忽略了。创建函数print.lsmobj <- function(obj) print('S3')(由于class(l)lsmobj)并运行cld(l)不会打印"S3"

showMethods(lsmobj)showMethods(ref.grid)(超类),请不要列出类似于cld函数的任何内容。

使用debugonce(multcomp::cld)显示最终调用的函数是cld.ref.grid中的lsmeans

但是,我想知道如何实现cld.ref.grid最终将被调用而没有像debugonce这样的“技巧”。也就是说,R执行哪些步骤才能到达cld.ref.grid

hangzhoushuangyu 回答:混合S3和S4时的方法分派

要注册S3方法,必须具有泛型。在这里,我为foo对象编写了一个简单的merMod方法:

> library(lme4)
> foo.merMod = function(object,...) { "foo" }

> showMethods(class = "merMod")

Function ".DollarNames":
 <not an S4 generic function>

Function "complete":
 <not an S4 generic function>

Function "formals<-":
 <not an S4 generic function>

Function "functions":
 <not an S4 generic function>
Function: getL (package lme4)
x="merMod"

Function "prompt":
 <not an S4 generic function>
Function: show (package methods)
object="merMod"

> methods(class = "merMod")
 [1] anova          as.function    coef           confint        cooks.distance
 [6] deviance       df.residual    drop1          extractAIC     family        
[11] fitted         fixef          formula        getL           getME         
[16] hatvalues      influence      isGLMM         isLMM          isNLMM        
[21] isREML         logLik         model.frame    model.matrix   ngrps         
[26] nobs           plot           predict        print          profile       
[31] ranef          refit          refitML        rePCA          residuals     
[36] rstudent       show           sigma          simulate       summary       
[41] terms          update         VarCorr        vcov           weights              

两个列表均不包含foo。但是,如果我们定义了通用名称,那么它将显示在methods()结果中:

> foo = function(object,...) UseMethod("foo")
> methods(class = "merMod")
 [1] anova          as.function    coef           confint        cooks.distance
 [6] deviance       df.residual    drop1          extractAIC     family        
[11] fitted         fixef          foo            formula        getL          
[16] getME          hatvalues      influence      isGLMM         isLMM         
[21] isNLMM         isREML         logLik         model.frame    model.matrix  
[26] ngrps          nobs           plot           predict        print         
[31] profile        ranef          refit          refitML        rePCA         
[36] residuals      rstudent       show           sigma          simulate      
[41] summary        terms          update         VarCorr        vcov          
[46] weights       

现在它包含foo

类似地,在您的示例中,如果您执行methods()cld将显示library(multcomp)的存在,因为这是cld的通用名称所在的地方。

,

较早的R文档(2016年前)用于包含比当前文档更多的详细信息,但粗略地说,该过程按优先级从高到低的顺序如下:

1)如果函数是标准的S4泛型且签名中的任何参数均为S4(根据isS4),则根据通常的规则选择最佳的S4方法。

2)如果该函数是非标准的S4泛型,则执行其主体,然后在某些时候调用其自身的S4分派。

3)如果该函数是S3泛型函数,则在第一个参数上进行S3调度(内部泛型二进制运算符除外)。

4)如果该函数根本不是通用函数,则将以常规方式对其所有参数进行惰性求值。

请注意,在setGeneric的帮助页面中:

“通过调用UseMethod来调度S3方法的函数是普通函数,而不是"genericFunction"类中的对象。它们与任何其他函数一样都具有通用性,但是为了确保S4和S3方法分派是一致的(请参阅Methods_for_S3)。”

本文链接:https://www.f2er.com/3166352.html

大家都在问