如果您运行t(a),其中a 是您的类test 的对象,则调用UseMethod("t")。这将检查您提供给t() 的第一个参数的类是什么。班级是test,R 现在将
寻找函数t.test()。因为t.test() 存在,所以t.test(a) 运行。这称为“方法分派”。
仅当t.test() 不存在时,R 才会求助于调用t.default()。实际上,您甚至可以通过在运行 t(a) 之前分离 stats 包来看到这种情况:
a <- structure(1:4, class = "test")
detach("package:stats")
t(a)
## [,1] [,2] [,3] [,4]
## [1,] 1 2 3 4
## attr(,"class")
## [1] "test"
现在的问题是,当您运行methods("t") 时,为什么t.test 不包含在列表中。当你查看methods() 的源代码时,你会注意到它调用了.S3methods()。该函数编译t 的所有方法的名称。但是,在某些时候,它会删除 S3MethodsStopList 中包含的函数名称:
info <- info[grep(name, row.names(info)), ]
info <- info[!row.names(info) %in% S3MethodsStopList,
]
(如果我在 RStudio 中运行 edit(.S3methods),这些是第 47 和 48 行)。
S3MethodsStopList 在前面定义(在第 15 行):
S3MethodsStopList <- tools:::.make_S3_methods_stop_list(NULL)
函数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"
简而言之,methods() 会明确过滤掉已知不是方法的函数。另一方面,方法分派只是寻找具有适当名称的函数。