0

我想了解混合 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

4

2 回答 2

1

为了注册 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()将揭示cldif you do的存在library(multcomp),因为这是通用 forcld所在的位置。

于 2019-11-04T14:50:17.533 回答
1

较旧的 R 文档(2016 年之前)过去包含比当前文档更多的详细信息,但粗略地说,该过程按优先级降序排列如下:

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

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

3) 如果函数是 S3 泛型函数,则 S3 分派发生在第一个参数上(内部泛型二元运算符除外)。

4) 如果函数根本不是泛型函数,则以通常的方式对其所有参数进行惰性求值来求值。

请注意,从帮助页面setGeneric

“通过调用调度 S3 方法的UseMethod函数是普通函数,而不是"genericFunction"类中的对象。它们像任何其他函数一样被通用化,但需要一些特殊注意事项来确保 S4 和 S3 方法调度是一致的(请参阅 Methods_for_S3)。”

于 2019-11-08T08:55:01.427 回答