学习笔记,仅供参考,有错必纠
参考自:《R的极客理想》-- 张丹
RC是Reference classes的简称,又被称为R5,RC不同于原来的S3和S4对象系统,RC对象系统的方法是在类中自定的,而不是泛型函数。RC对象的行为更类似于其他的编程语言,实例化对象的语法也有所改变。但由于RC对象系统还是依赖于S4对象系统,我们可以简单地理解为RC是对S4的更进一步的面向对象封装。
RC对象系统以类为基本类型,有专门的类的定义函数setRefClass和实例化对象的生成方法。
语法:
setRefClass(Class, fields = , contains = , methods =,
where =, inheritPackage =, ...)
参数列表:
参数 | 解释 |
---|---|
Class | 定义类名 |
fields | 定义属性和属性类型 |
contains | 定义父类,继承关系 |
methods | 定义类中的方法 |
where | 定义存储空间 |
创建一个RC类:
#定义一个RC类
User <- setRefClass("User", fields = list(name = "character"))
实例化一个RC对象:
#实例化一个User对象u1
u1 <- User$new(name = "u1")
u1
#输出start
Reference class object of class "User"
Field "name":
[1] "u1"
#输出end
class(User)
#输出start
[1] "refObjectGenerator"
attr(,"package")
[1] "methods"
#输出end
is.object(User) #TRUE
otype(User) #"RC"
class(u1)
#输出start
[1] "User"
attr(,"package")
[1] ".GlobalEnv"
#输出end
is.object(u1) #TRUE
otype(u1) #"RC"
#创建RC类User
User <- setRefClass("User", fields = list(name = "character"))
#创建User的子类Member
Member<-setRefClass("Member", contains = "User",
fields = list(manage = "User"))
#实例化User
manager <- User$new(name = "manager")
#实例化一个Member对象
menber <- Member$new(name = "menber", manage = manager)
#查看member对象
menber
#输出start
Reference class object of class "Member"
Field "name":
[1] "menber"
Field "manage":
Reference class object of class "User"
Field "name":
[1] "manager"
#输出end
#查看member对象的name属性
menber$name #"menber"
#检查对象的属性类型
otype(menber$name) #"base"
otype(menber$manage) #"RC"
RC的类有一个指定构造器方法$initialize()
,这个构造器方法在实例化对象时,会自动被运行一次,通过这个构造方法可以设置属性的默认值。
#定义一个RC类, 并设置默认值
User <- setRefClass("User", fields = list(name = "character", level = "numeric"),
methods = list(
initialize = function(name, level) {
print("User::initialize自动执行")
name <<- "Huang"
level <<- 12
}
))
#实例化对象
u1 <- User$new() #"User::initialize自动执行"
#查看对象u1,属性被增加了默认值
u1
#输出start
Reference class object of class "User"
Field "name":
[1] "Huang"
Field "level":
[1] 12
#输出end
#定义User类
User <- setRefClass("User",
fields = list(name = "character", age = "numeric",
gender = "factor"))
#定义一个factor类型
genderFactor <- factor(c("F", "M"))
#实例化u1
u1<-User$new(name = "u1", age = 30, gender = genderFactor[1])
#查看age属性值
u1$age #30
u1$gender
#输出start
[1] F
Levels: F M
#输出end
给u1的age属性赋值:
u1$age <- 10
u1$age #10
把u1对象赋值给u2对象:
#把u1赋值给u2对象
u2 <- u1
#查看u2的age属性
u2$age #10
#重新赋值
u1$age <- 20
#查看u1, u2的age属性
u1$age #20
u2$age #20
由于把u1赋值给u2的时候,传递的是u1的实例化对象的引用,而不是值本身,这一点与其他语言中对象赋值是一样的。
如果想进行赋值而不是引用传递,可以用下面的方法实现:
#调用u1的内置方法copy,赋值给u3
u3 <- u1$copy()
#查看u3的age属性
u3$age #20
#重新赋值
u1$age <- 30
#查看u1的age属性,发生改变
u1$age #30
#查看u3的age属性,没有改变
u3$age #20
在RC对象系统中,方法可以定义在类的内部,通过实例化的对象完成方法调用。
User <- setRefClass("User",
fields = list(name = "character", favorite = "vector"),
methods = list(
addFavorite = function(x) {
favorite <<- c(favorite, x)
},
delFavorite = function(x) {
favorite <<- favorite[-which(favorite == x)]
},
setFavorite = function(x) {
favorite <<- x
}
))
#实例化对象
u1 <- User$new(name = "u1", favorite = c("movie", "football"))
u1$favorite #"movie" "football"
#删除一个兴趣
u1$delFavorite("football")
#增加一个兴趣
u1$addFavorite("reading")
u1$favorite #"movie" "reading"
#重新设置兴趣列表
u1$setFavorite(c("game", "reading"))
u1$favorite #"game" "reading"
对于RC的实例化对象,除了我们自己定义的方法,还有几个内置的方法,属性复制赋值时使用的copy方法,就是其中之一。
内置方法 | 作用 |
---|---|
initialize | 类的初始化函数,用于设置属性的默认值,只能在类定义的方法中使用 |
callSuper | 调用父类的同名方法,只能在类定义的方法中使用 |
copy | 复制实例化对象的所有属性 |
initFields | 给对象的属性赋值 |
field | 查看属性或给属性赋值 |
getClass | 查看对象的类定义 |
getRefClass | 同getClass |
show | 查看当前对象 |
export | 查看属性值,以类为作用域 |
import | 把一个对象的属性值赋值给另一个对象 |
trace | 跟踪对象中方法调用,用于程序debug |
untrace | 取消跟踪 |
usingMethods | 用于实现方法调用,只能在类定义的方法中使用 |
RC对象实例化后,有两个内置属性。
内置方法 | 作用 |
---|---|
.self |
实例化对象自身 |
.refClassDef |
类的定义类型 |
当我们定义好一个RC的类时,有一些辅助函数可以帮助我们查看类的属性和方法,用于创建实例化的对象的$new()
函数,也属于这类辅助函数.
辅助函数 | 含义 |
---|---|
new | 实例化对象 |
help | 查询类中方法的调用 |
methods | 列出类中定义的所有方法 |
fields | 列出类中定义的所有属性 |
lock | 给属性加锁,实例化对象的属性只允许赋值一次,即赋值变量,不可修改 |
trace | 跟踪方法 |
accessors | 给属性生成get/set方法 |