S3 形式での多態

実はちゃんとやったことがなかった。

a <- list()
class(a) <- "TestClass"
testfunc <- function(x) {print("test func")}
testfunc(a) # test func
testfunc.TestClass <- function(x) {print("test func for TestClass")}
testfunc.TestClass2 <- function(x) {print("test func for TestClass2")}
testfunc(a) # test func
testfunc <- function(x) {UseMethod("testfunc")}
testfunc(a) # test func for TestClass
b <- list()
class(b) <- "TestClass2"
testfunc(b) # test func for TestClass2
testfunc(1) # double, numeric に適用できるメソッドがないというエラーになる
class(1)
testfunc.default <- function(x) {print("test func for others")}
testfunc(1) # test func for others

UseMethod を呼び出す関数を設定してはじめてポリモフィズムが実現するようだ。最初から与えられている関数(plot や summary) については、既に UseMethod を呼び出す部分が定義済みなので、plot.TestClass のような関数を定義するだけで動いてしまうから気付かなかった。

なお、UseMethod は本当は UseMethod(generic, object) という形を取るらしいが、object 引数を省略すると、呼び出し元の関数(testfunc)の第一引数(x)が自動的に渡されるらしい。これはどういう仕組み?

#TODO: internal generic, group generic, NextMethod について