はじめに
あまり有名ではない事実かもしれませんが、Rでもパッケージを専用の使えばオブジェクト指向っぽい使い方ができます。
特にここではR6というパッケージを使ったオブジェクト指向プログラミングを研究してみます。
他にも、似たようなパッケージでS3,S4(Google社内のコード規約ではこれが推奨されている)、RCメソッドなどがあります。
が、R6が最も普通にOO言語っぽい書き方ができると聞きました。とりま下記は普通にできるようです。
・クラスとインスタンスの作成
・メンバ変数とクラスメソッドの 作成
・インスタンス作成時のコンストラクタの発動
・プライベートメソッドとパブリックメソッド(または変数)の使い分け
・継承(私の方ではまだ未検証)
・ などなど
参考資料
TokyoRで発表された実にまとまっているSlideShareの資料
http://www.slideshare.net/__nakamichi__/r6-upload?ref=
ここでいうフィールドっていうのは要はメンバ変数のことらしい
フィールドとメソッドは、PublicにすることもPrivateにすることもできる
ただし、Pythonのように変数やメソッドごとにPublicとPrivateを指定するのではなく、
PublicとPrivateに入れるものはまとめて定義する
http://www.slideshare.net/hiroki84/r6-classes-42764598
http://qiita.com/hoxo_m/items/23b10243b6ffbea33a80
サンプルコード
まずクラスを作ります
# R6パッケージをインストールする
install.packages("R6")
library(R6)
Person <-
# 「Person」というクラスを作ってみます。
R6Class("Person",
public = list(
# クラスの外から呼べるメンバは、public = list()の中にlist形式で記述します
# メンバ変数もクラスメソッドも、このListの中にザクザク書いていけばOK
# プライベート変数、プライベートメソッドは private = list()で
# 別途定義する必要があります(後述)
name = NA, # メンバ変数、デフォルト値なし
hair = "black", # メンバ変数、デフォルト値有り
initialize = function(name, hair){
#コンストラクタは、"initialize"という名前の関数が該当します。(
#メンバ変数はself$で記述
self$name <- name
self$hair <- hair
},
#メソッドを定義
set_hair = function(hair) self$hair = hair,
greet = function(greet) print(paste(greet," I am ",self$name))
)
)
注意すべき点は、
public = list(
name = NA,
hair = "black",
のように、クラス内に登場するメンバ変数のデフォルト値を設定しておかなければ
いけないということ。
そうでないと次のようなエラーが吐かれます。
cannot add bindings to a locked environment
また、ここで指定したデフォルト値がメンバ変数の型となります。
デフォルト値で数値型を代入していると、のちのコンストラクタやメソッドで
文字列型などを代入することができなくなります。
インスタンスを作成し、操作してみます
# インスタンスは、ClassName$new(arg)で作ります。
# 赤髪の山田さんというPersonインスタンスを作ってみます。
Yamama_Person <- Person$new("yamada","red")
print Yamama_Person # print文で普通にメンバの一覧が見れる
# クラスメソッドの"greet"を使って挨拶をさせてみます。
Yamama_Person$greet("hello")
Yamama_Person$greet("good morning")
# 髪の色を操作
Yamama_Person$hair #メンバ変数 "hair"の初期値を確認
[1] "red"
Yamama_Person$set_hair("blue") #メンバ変数 "hair"を変更する"set"メソッドを行使
Yamama_Person$hair #再確認
[1] "blue"
プライベートメソッドの使い方はこちら
Person <-
R6Class("Person",
private = list(
# プライベートのメンバはprivate = list()の中にlist形式で記述します
# Publicとは別のList内に記述していきます
age = NA,
get_age = function()private$age #プライベート変数を呼び場合は、self$でなく、private$で呼び出す
),
public = list(
# クラスの外から呼べるメンバは、public = list()の中にlist形式で記述します
# メンバ変数もクラスメソッドも、このListの中にザクザク書いていけばOK
# プライベート変数、プライベートメソッドは private = list()で別途定義する必要があります(後述)
name = NA,
hair = "black",
initialize = function(name, hair, age){
self$name <- name
self$hair <- hair
private$age <- age #プライベートメソッドを呼び場合は、self$でなく、private$で呼び出す
},
set_hair = function(hair) self$hair = hair,
greet = function(greet) print(paste(greet," I am ",self$name)),
show_age = function() private$get_age() -5
)
)