R有三种底层对象系统,S3,S4,RC。
在R语言中,基于S3对象的面向对象编程,是一种基于泛型函数的实现方式。
我们为什么需要S4对象,因为S3对象太过模糊,很容易搞得很复杂,所以便出现了S4对象,这个作为面对对象编程的定义更为清晰。特别是Bioconductor社区,以S4对象系统作为基础架构,只接受符合S4定义的R包。
那么还要不得不问一个关键问题,为什么R之中需要面向对象编程?我们直接使用某些函数不好吗?因为任何一个函数其实就是一堆数据结构和函数的结合。直接使用面向过程编程不好吗?答案当然是可以的。但是这样对于小的项目还好,对于大的项目开发来说,这样不利于代码的后续维护和继续开发。
我们应该记住的是,面向对象编程其实就是为了减少后续维护的麻烦,减少代码总体上的复杂性。但是这是针对大一点的项目而言的,如果只是很简单的几行代码,我们其实不一定要写成面向对象的形式,只是简单的函数定义便可。
setclass()函数的定义
□ Class:定义类名。
□ slots:定义属性和属性类型。
□ prototype:定义属性的默认值。
□ contains=character():定义父类,继承关系。
□ validity:定义属性的类型检查。
□ where:定义存储空间。
□ sealed:如果设置TRUE,则同名类不能被再次定义。
□ package:定义所属的包。
□ S3methods:R3.0.0以后不建议使用。
□ representation:R3.0.0以后不建议使用。
□ access:R3.0.0以后不建议使用。
□ version:R3.0.0以后不建议使用。通过setClass()函数我们就可以创建一个S4类型的对象结构了
普通函数
work<-function(x) cat(x,'is working')
work("human")
S4类型编写函数:把原来的函数定义及调用过程从2步变成4步:(1)定义数据对象类型;(2)定义接口函数(泛型函数);(3)定义实现函数;(4)把数据对象以参数传入接口函数,执行实现函数。
setClass("Person",slots = list(name="character",age="numeric")) #定义数据对象类型
setGeneric("work",function(object) standardGeneric("work")) #定义接口函数
setMethod("work",signature(object="Person"),function(object) cat (object@name,"is working")) #定义实现函数
a<-new("Person",name="happy",age=16) #把数据对象以参数的传入接口,执行实现函数
a
work(a)
library(pryr)
ftype(work)
work
showMethods(work)
getMethod("work","Person") #查看person对象的work函数实现
产生的结果
补充说明:这里着重讲一下接口函数或者说泛型函数这东西,之前写这个的时候自己的理解还不是很到位,但是读了R面向对象编程之后感觉自己又进一步理解了,什么叫泛型函数,通俗来讲就是一类动作的总称,比如跑步是一类总的动作概念,但是这个概念下面针对不同的对象又有不同的改变,比如人是两条腿在跑,马要用四条腿等等,在R之中就有大量的泛型函数,比如mean等,所以要实现这种泛型函数有两种方式,一是自己造,所以有standardgeneric,要么是直接继承原本的有的泛型函数(就是给原本有的大类增加针对新的对象的子类),比如你写了一个list的对象,然后你要求mean,但是直接用mean这个泛型函数你是无法直接得出mean,那么这个时候就要自己给mean增加一个子类,mean.xx,这样mean就会专门针对你的新定义的对象进行求mean了。
所以这里S4的面向对象编程就相当于首先我们要创造一种生物(定义数据对象类型),然后我们要创造一种动作(定义泛型函数或者说接口函数),比如跑步,然后我们要将这类生物和跑步这个动作关联起来(定义实现函数),然后我们把这种生物的个体确定下来(就是我们赋予了这个个体具体的参数),然后我们就可以用跑步这个动作去看看这个生物个体跑的怎么样(把数据对象以参数传入接口函数,执行实现函数。)
接着说一下R的这种面向对象和python的不同(主要是基于目前本人的浅显理解,如果有问题请指正),最大的区别应该就在于动作和生物属性之间的分离,S4的面向对象需要方法函数(也就是上面的动作)和数据的主体对象(也就是上面的生物属性)分开去定义的,然后再关联起来,但是经常我们使用python的class是直接定义了数据的主体对象之后后面就要加上方法函数,简单比喻来说python的类是"我们直接定义某一类生物能够完成一定的动作",而S4就相当于"有一类生物,有一类大动作,这类大动作的下面的一些小动作是能够被这类生物完成的"。
来源:《R的极客理想:高级开发篇》
R语言面向对象编程 (dataxujing.github.io)