我正在阅读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来自哪里?
如果你运行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()明确过滤掉已知不是方法的函数.另一方面,方法调度只是查找具有适当名称的函数.