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 について