R语言面向对象之R6 class
(本文是AdvancedR的R6章节的整理)
R6是R语言和现在OOP语言比较接近的一个实现方式,其对象是可变的(mutable),基于S3和environment。
# install.packages("R6")
library(R6)
类定义class declaration
ClassName <- R6Class("ClassName", list(
field1 = 0,
method1 = function(x = 1) {
self$field1 <- self$field1 + x
invisible(self)
})
)
对象创建object creation
采用class$new()方式
x <- Accumulator$new()
x$add(10)
x$sum # x$sum = 10
注意Accumulator$add实现方式,返回该对象,使得对象可以使用链式调用。
对象初始化和终结处理object initialization and finalizer
直接看例子:
TemporaryFile <- R6Class("TemporaryFile", list(
path = NULL,
initialize = function() {
self$path <- tempfile()
},
finalize = function() {
message("Cleaning up ", self$path)
unlink(self$path)
}
))
initialize: 创建对象的时候可以从class$new()传入参数,完成对象的初始化。
finalize: 对象被删除rm()或垃圾回收的时候,调用该函数(资源释放)
对象打印输出print
class可以定义print函数,这样在环境中可以直接输出对象的内容。
对象克隆clone
R6对象是采用引用方式,赋值指向的还是同一个对象。若要想R语言的普通对象赋值copy方式,需要使用object$clone()
函数,默认是浅拷贝,深拷贝需要 object$clone(deep = TRUE)
.
类动态修改
Class可以动态设置/增加成员函数或成员变量
Class$set("public", "field/method member", field init value / functioin definition)
操作不会影响已经创建的对象。
继承Inheritance
AccumulatorChatty <- R6Class("AccumulatorChatty",
inherit = Accumulator,
public = list(
add = function(x = 1) { # override the parent method.
cat("Adding ", x, "\n", sep = "")
super$add(x = x) # delegate to super method
}
)
)
访问控制 controlling access
有三种方式public/private/active,类定义的时候直接写:
public = list(...)
private = list(...)
active = list(...)
active使用了active binding的方式:
Rando <- R6::R6Class("Rando",
active = list(
random = function(value) {
if (missing(value)) {
runif(1)
} else {
stop("Can't set `$random`", call. = FALSE)
}
}
)
)
x <- Rando$new()
x$random
#> [1] 0.0808
x$random
#> [1] 0.834