2012年12月19日水曜日

Rでオブジェクト指向 (S3)

RにはS3, S4, R5の3種類のクラスがある。S3はclass属性で判定しているだけの緩やかな型付け。S4は厳格に定義しておく必要がある厳格な型付け。R5は2.12で追加された新しいクラスで、厳格さはS3とS4の中間。参照渡しという大きな特徴がある。

今回はS3クラスについて。まだS4, R5は理解していないし、"Google's R Style Guide"がS3を推奨しているので、まずはS3から勉強している。
Use S3 objects and methods unless there is a strong reason to use S4 objects or methods.
Google's R Style Guide
S3クラスができるのは、class属性と汎用関数を使ってポリモーフィズムを与えること。つまり、クラスごとに同じ名前で異なる実装の関数を呼び出せる。printやsummaryが分かりやすい例だと思う。

自分で簡単な例を実装してみる。

まず、インスタンスにクラスを教える。S3クラスではclass属性にベクトルを設定するだけ。ベクトルなので、複数のクラスを設定できる。この例では、hogeクラスやfugaクラスを設定している。
a <- 1:10
attr(a, "class") <- "hoge"

b <- 1:10
attr(b, "class") <- c("fuga", "hoge")

c <- 1:10
続いて、汎用関数を宣言・実装する。Javaでいう抽象メソッドを宣言してから、クラスごとに実装していくイメージ。最後の.defaultはデフォルト実装で、対応するクラスがないときに呼ばれる。
calc <- function(x, ...) {
  UseMethod("calc")
}

calc.hoge <- function(x){
  return (x + x)
}

calc.fuga <- function(x) {
  return (x * x)
}

calc.default <- function(x) {
  return (x + 1)
}
実際に呼び出すと、class属性に応じて違う実装が呼び出されていることが確認できる。calc(b)でcalc.fugaが呼ばれていることから、ベクトルを先頭から探しているみたい。
calc(a)
# calc.hoge is called
# 2  4  6  8 10 12 14 16 18 20

calc(b)
# calc.fuga is called
# 1   4   9  16  25  36  49  64  81 100

calc(c)
# calc.default is called
# 2  3  4  5  6  7  8  9 10 11
これでポリモーフィズムが使える。ということは、ポリモーフィズムを活用しているデザインパターンも適用できるはず。

References

0 件のコメント:

コメントを投稿