総称的関数

総称的関数は 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{
...
}