R5 reference class覚え書き

R2.12から実装されたR5クラスの覚え書きです。日本語の情報はまだないみたいなので一番乗りを狙って。ちなみに継承関係は、面倒なので完全に無視してます。ごめんなさい。その他、網羅性は期待しないでください。

R5クラスの特徴

  • 参照渡し
  • オブジェクトを編集できる
  • S4より緩くて使いやすい

他にもあると思いますが、触ってみた感想ということで。

とりあえずクラス定義

tc <- setRefClass(Class="testClass",
        fields = list(f1="numeric", f2="numeric"),
        methods = list(
          foo = function() {
            "f1とf2を足し合わせるメソッド"
            f1 + f2
          }))

R5クラスはsetRefClass()で定義します。主に使うオプションは、Classとfieldsとmethodsです。Classでクラス名を定義します。fieldsにはオブジェクトの持つフィールドの名前を文字列ベクトルかリストで定義します。リストの場合は、list(名前="クラス",...)という形で、フィールドのクラスを定義します。リストを使ってフィールドのクラスを定義した場合、オブジェクトの作成時に型チェックが行われます。型が合わない場合はエラーではなく強制変換されます。たとえ強制変換の結果がNAであっても(警告は出るものの)オブジェクトは生成されるので、注意が必要です。文字列ベクトルで定義した場合は当然型チェックは行われません。methodsにはメソッドをリストで定義します。関数定義の一行目に文字列を書くと、メソッドのヘルプと認識されます。メソッド内では、フィールドに定義した変数を自由に使うことができます。

setRefClass()はgenerator objectを返します。generator objectは、オブジェクトを生成したり、メソッドをクラスに追加するときなどに使います。ちなみにgenerator objectもR5クラスです。

generator object

generator objectはクラスを管理するために使われるので、結構重要です。

test <- tc$new(f1=1, f2=2)
tc$accessors("f1", "f2")
tc$help(foo)
tc$methods(
  bar=function(x){
    f1 <<- f1 + x
  })

前述のとおり、generator object自身もR5クラスなので、各種メソッドを持っています。R5クラスのメソッドは、オブジェクト$メソッド(...)という形で使います。1行目は、newメソッドでオブジェクトを生成しています。accessorsメソッドは、フィールドのgetterとsetterを自動的に定義してくれます。これを実行すると、getF1、setF1、getF2、setF2というメソッドが追加されます。helpメソッドは、メソッドのヘルプを見るためのメソッドです。methodsメソッドは、引数なしで実行した場合はメソッドの一覧を表示します。上の例のようにすれば、メソッドを新たに追加することができます。ちなみに、例のようにメソッド内で<<-を使うことで、フィールドを上書きすることができます。

オブジェクトをいじってみる

> test$foo()
[1] 3
> test$bar(10)
> test$getF1()
[1] 11
> test$foo()
[1] 13
> test$setF2(5)
> test$foo()
[1] 16

その他重要なこと

  • initializeメソッドはオブジェクトを生成するときに実行される
  • finalizeメソッドはガベージコレクションによってオブジェクトが消去される前に実行される
  • メソッド内で、.selfはオブジェクト自身を意味する
  • R5クラスオブジェクトを参照渡しでなくコピーしたいときは、copyメソッド