R5 クラスは R で定義できるクラスの一種で、R 2.12 以上のバージョンで利用できる。R5 はリファレンスクラスとも呼ばれ、オブジェクトは参照渡しにより受け渡しを行う。
R5 クラスの定義
R5 クラスの定義は setRefClass
を利用する。クラス名、定義フィールド、クラスのメソッドの順に定義する。次は、Asagao
クラスを R5 で定義する例である。
クラスの定義
Asagao <- setRefClass(
# クラス名
Class = "Asagao",
# フィールド
fields = list (
color = "character", # 花の色
leaves = "numeric", # 葉っぱの枚数
conditions = "numeric", # 生育状態
seeds = "numeric" # 種の数
),
# メソッド
methods = list (
# 葉っぱの枚数から生育状態を計算して、その状態を condionts 変数に保存
CalcConditions = function() {
x <- 1.12
y <- 31.2
conditions <<- leaves * x - y
},
# 現在の生育状態から種子数を予測し、予測した種指数を seeds に保存
EstimateSeeds = function() {
seeds <<- round(conditions / 10 + 50)
}
)
)
フィールド値の取得と更新
クラスからオブジェクトを生成するときに new
関数を利用する。初期値がある場合は new
関数に引数として与える。
# 青い朝顔を作成
blue.asagao <- Asagao$new(color="blue", leaves=50) # この方法を推奨
# 青い朝顔の生育状態を計算する
blue.asagao$CalcConditions()
blue.asagao$conditions
## [1] 24.8
# 赤い朝顔を作成
red.asagao <- Asagao$new()
red.asagao$color <- "red" # この方法による初期化は非推奨
red.asagao$leaves <- 100
# 赤い朝顔の生育状態を計算し、種指数を予測する
red.asagao$CalcConditions()
red.asagao$EstimateSeeds()
red.asagao$seeds
## [1] 58
# field を利用してフィールドを取り出す方法
red.asagao$field("leaves")
## [1] 100
オブジェクトのコピー
R5 クラスのオブジェクトをコピーする場合は copy
メソッドを利用する。R5 クラスのオブジェクトはリファレンス(メモリーのアドレス・宛先)であるから、new_obj <- old_obj
と実行しても、new_obj
と old_obj
は同じ宛先を指すため、両者全く同じものである。そのため、R5 クラスのオブジェクトをコピーするときは copy
を利用する必要がある。
# <- を利用した場合
asagao.1 <- Asagao$new(color="red", leaves=50)
asagao.2 <- asagao.1
# asagao.2 を変更
asagao.2$color <- "blue"
# asagao.1 も変換されてしまう(asagao.2 と asagao.1 が同じ宛先であるため)
asagao.1$color
## [1] "blue"
# copy を利用して R5 クラスのオブジェクトをコピー
asagao.3 <- asagao.1$copy()
asagao.3$color <- "pink"
# asagao.3 を変換しても asagao.1 は変換されない
asagao.1$color
## [1] "blue"
コンストラクタ
setRefClass
で定義された R5 クラスのコンストラクタは new
である。コンストラクタの動作は initialize
で定義する。クラスからオブジェクトを生成するときに、初期化しておきたいフィールドがあれば、initialize
内で定義する。
Asagao <- setRefClass(
Class = "Asagao",
fields = list (
color = "character", # 花の色
leaves = "numeric", # 葉っぱの枚数
conditions = "numeric" # 生育状態
),
methods = list (
# コンストラクタ
initialize = function(color=NULL, leaves=NULL) {
if (is.null(color)) {
color <<- "skyblue"
} else {
color <<- color
}
if (is.null(leaves)) {
leaves <<- 50
} else {
leaves <<- leaves
}
},
CalcConditions = function() {
conditions <<- leaves * 10 - 5
}
)
)
以下のように引数なしで new
を実行したとき、color
と leaves
フィールドはそれぞれ skyblue
と 50
に初期化される。
skyblue.asagao <- Asagao$new()
skyblue.asagao$color
## [1] "skyblue"
skyblue.asagao$leaves
## [1] 50
継承
他のクラスを継承するには contains
で定義する。
Flower <- setRefClass(
Class = "Flower",
fields = list (
color = "character",
leaves = "numeric",
conditions = "numeric"
)
)
# Flower クラスを継承する Asagao クラス
Asagao <- setRefClass(
Class = "Asagao",
# 継承
contains = c("Flower"),
fields = list(
species = "character"
),
methods = list(
getConditions = function() {
conditions <<- 2 * leaves
return(conditions)
}
)
)
asagao <- Asagao$new(leaves=20, species="momomurasaki")
asagao$getConditions()
## [1] 40