総称的関数は R で定義されている関数の概念。plot
関数などがその代表例である。総称的関数として定義された関数は、与えられた引数のクラスを判別して、そのクラスで定義された動作をする。
x <- 1:10
y <- 11:20
r <- lm(y~x)
plot(x) # 数値(integer クラス)を与えると、点が描かれる
plot(r) # 回帰式(lm クラス)を与えると、QQ プロットなどが描かれる
総称的関数は setGeneric
を利用して動作を定義し、setMethod
を利用してクラスとその関数を結び付ける。
既存の総称的関数にクラスを結びつける
plot
関数は R では総称的関数として定義されている。ここでは、Freesia
クラスを作成し、Freesia
クラスを plot
関数に結びつける例を示す。
# Freesiaクラスの定義
setClass(
Class = "Freesia",
representation (
data = "matrix",
x = "numeric",
y = "numeric"
),
prototype = list(
data = matrix(0),
x = 0,
y = 0
)
)
# plot 関数を Freesia クラスを結びつける
setMethod(
f = "plot",
signature(x = "Freesia"),
definition = function(x, ...) {
plot(x@x, x@y, type = "h", col = "orange", ...)
}
)
このように定義された plot
関数に対して、数値データ(integer
クラス)と Freesia
クラスのデータを与えると、異なる動作をする。
x <- 1:10
y <- 1:10
## 左下の図
plot(x, y)
freesia <- new("Freesia", x = x, y = y) # Freesia クラスのオブジェクトを作成
## 右下の図
plot(freesia)
他のライブラリーに含まれている関数と同じ名前の総称的関数を作る
他のライブラリーに含まれている関数を、自作のライブラリーにて総称的関数として定義することができる。
getData
関数を、Freesia
パッケージに含まれている、総称的関数として定義されていない関数とする。
setClass(
Class = "Freesia",
representation (
data = "matrix"
),
prototype = list(
data = matrix(0),
)
)
getData <- function(x) {
return(x@data)
}
その getData
関数を Freesia
パッケージで総称的関数として定義する場合は次のように行う。
# Freesia をロード
library(Freesia)
# 総称的関数を定義
setGeneric(name = "getData", def = function(object, ...) { object })
# Freesia パッケージ向けの getData を再定義
setMethod(
f = "getData",
signature(object = "Freesia"),
definition = function(object, ...) {
return(Freesia::getData(object, ...)) # Freesia クラスの getData に飛ばす
}
)
# Freesia パッケージ向けの getData を定義
setMethod(
f = "getData",
signature(object = "Freesia"),
definition = function(object, x, y, z) {
t <- object@data * x / y + z
return(t)
}
)
総称的関数の R ドキュメントについて
総称的関数として定義されている関数の R ドキュメント(.Rd)は、「クラス-関数名」の順で alias
を付ける。また、usage
は \S4method
などを用いて表す。
\name{getData}
\docType{methods}
\alias{getData,Freesia-method}
\alias{getData,Asagao-method}
\alias{getData}
\title{Get data from an object}
\description{
Get data from an object.
}
\usage{\S4method{getData}(object, x, y, z)}
\arguments{
...
}