为什么函数t为类设置为"test"的对象返回t.test?

M4R*_*NK4 5 r

我正在阅读Hadley Wickham的书籍Advanced R,特别是OO fied指南(http://adv-r.had.co.nz/OO-essentials.html).该章的第一个练习如下:

阅读t()和t.test()的源代码,并确认t.test()是S3泛型而不是S3方法.如果用类测试创建一个对象并用它调用t()会发生什么?

如果我正确理解了这一章,我们可以确认t()和t.test()是通用的,因为它们在源代码中使用UseMethod()函数.methods(t)返回t.data.frame,t.default和t.ts*作为函数t()的方法.那么,如果两者都是S3泛型并且t没有t.test方法,那么下面的代码是否返回t检验?

a <- structure(1:4, class = "test")
t(a)
Run Code Online (Sandbox Code Playgroud)

我的预测是t将使用类"test"的默认方法而t.default(a)在逻辑上将转置作为我认为它应该.那时t.test来自哪里?

Sti*_*ibu 6

如果你运行t(a),a你的类的对象在哪里test,然后 UseMethod("t")被调用.这将检查您提供的第一个参数的类是什么t().该类是test,R现在将寻找一个函数t.test().既然t.test()存在,t.test(a)就是奔跑.这称为"方法调度".

只有在t.test()不存在的情况下,R才会求助于召唤t.default().实际上,您甚至可以通过stats在运行之前分离包来看到这种情况t(a):

a <- structure(1:4, class = "test")
detach("package:stats")
t(a)
##      [,1] [,2] [,3] [,4]
## [1,]    1    2    3    4
## attr(,"class")
## [1] "test"
Run Code Online (Sandbox Code Playgroud)

现在的问题是t.test,当你运行时,为什么不包含在列表中methods("t").当你查看源代码时methods(),你会注意到它的调用.S3methods().该函数编译所有方法的名称t.但是,在某些时候,它会删除包含在S3MethodsStopList以下内容中的函数名称:

info <- info[grep(name, row.names(info)), ]
info <- info[!row.names(info) %in% S3MethodsStopList, 
    ]
Run Code Online (Sandbox Code Playgroud)

(如果我在RStudio中运行编辑(.S3方法),这些是第47和48行).

S3MethodsStopList 先前已定义(第15行):

S3MethodsStopList <- tools:::.make_S3_methods_stop_list(NULL)
Run Code Online (Sandbox Code Playgroud)

该函数tools:::.make_S3_methods_stop_list()似乎没有记录,但它似乎只返回一个包含点的函数名称的硬编码列表,但实际上不是方法.t.test()是其中之一:

grep("^t\\.", tools:::.make_S3_methods_stop_list(NULL), value = TRUE)
##                 Hmisc6             calibrator                 mosaic               mratios1 
##       "t.test.cluster"                "t.fun"               "t.test"        "t.test.ration" 
##               mratios2               mratios3                 stats6 
## "t.test.ratio.default" "t.test.ratio.formula" 
Run Code Online (Sandbox Code Playgroud)

简而言之,methods()明确过滤掉已知不是方法的函数.另一方面,方法调度只是查找具有适当名称的函数.