If you run t(a) , where a is your object of class test , UseMethod("t") called. This will verify what the class of the first argument you provided t() . The class is test and now R find the function t.test() . Since t.test() exists, t.test(a) is t.test(a) . This is called the "submit method".
Only if t.test() does not exist does R resort to calling t.default() . You can even see this by disconnecting the stats package before running 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"
The question is why t.test not listed when methods("t") run. When you look at the source code for methods() , you will notice that it calls .S3methods() . This function compiles the names of all methods t . However, at some point, it deletes the function names that are contained in the S3MethodsStopList :
info <- info[grep(name, row.names(info)), ] info <- info[!row.names(info) %in% S3MethodsStopList, ]
(If I start editing (.S3methods) in RStudio, these are lines 47 and 48).
S3MethodsStopList defined earlier (on line 15):
S3MethodsStopList <- tools:::.make_S3_methods_stop_list(NULL)
The tools:::.make_S3_methods_stop_list() function does not seem to be documented, but it looks like it returns a hard list of function names containing a period, but not really methods. t.test() is one of them:
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"
In short, methods() explicitly filters functions that are not known to be methods. On the other hand, submitting a method is simply looking for a function with the appropriate name.