R语言面向对象编程:S3和R6

2017-06-10

0

R语言面向对象编程:S3和R6

一、基于S3的面向对象编程

基于S3的面向对象编程是一种基于泛型函数(generic function)的实现方式。

1.S3函数的创建

S3对象组成:generic(generic FUN)+method(generic.class FUN)

泛型函数(generic)创建示例:

get_n_elements

{

UseMethod("get_n_elements")

}

通常用UseMethod()函数定义一个泛型函数的名称,通过传入参数的class属性,来确定对应的方法调用。

method(generic.class)函数,创建示例:

# Create a data.frame method for get_n_elements

get_n_elements.data.frame

{

nrow(x) * ncol(x) # or prod(dim(x))

}

# Create a default method for get_n_elements

#在使用UseMethod调用时,先在methods中寻找对应class,如果都没有找到,则会调用#default方法。

get_n_elements.default

{

length(unlist(x))

}

methods() 用于查找S3泛型函数中所有可用的methods。

调用pryr包中的is_s3_method() 可以验证函数是否S3方法。

2、S3对象的传入参数有多个class属性的处理方法

当变量x具有多个class属性,应按具体到通用的顺序来排列变量对应的class。

使用NextMethod()来调用methods

an_s3_method.some_class

{

# Act on some_class, then

NextMethod("an_s3_method")

}

具体示例如下:

# Assign classes

class(kitty)

what_am_i

{

UseMethod("what_am_i")

}

# cat method

what_am_i.cat

{

message("I'm a cat")

NextMethod("what_am_i")

}

# mammal method

what_am_i.mammal

{

message("I'm a mammal")

NextMethod("what_am_i")

}

# character method

what_am_i.character

{

message("I'm a character vector")

}

二、基于R6的面向对象编程

1、R6对象的创建

首先使用 R6Class() 创建一个class generator(也可叫factory)。

第一个参数是创建的对象的类的名字。

参数private为一个list,为对象保存数据域(data field),包含每个元素的名字。

参数pubilc为一个list,为对象保存面向用户的函数或功能。

library(R6)
thing_factory

"Thing",

private = list(

a_field = "a value",

another_field = 123

),

public = list(

do_something = function(x, y, z) {

# Do something here

}

)

)

创建factory后,再调用new()来生成一个R6对象。new()无需定义,所有的factory都默认具有该方法。

a_thing

initialize()是一种特殊的公有方法(public method), 在R6对象创建时自动调用,用来设置私域(private field)值。

new()中的参数被传给initialize()。

# Add an initialize method

microwave_oven_factory

"MicrowaveOven",

private = list(

power_rating_watts = 800,

door_is_open = FALSE

),

public = list(

cook = function(time_seconds) {

Sys.sleep(time_seconds)

print("Your food is cooked!")

},

open_door = function() {

private$door_is_open = TRUE

},

close_door = function() {

private$door_is_open = FALSE

},

# Add initialize() method here

initialize = function(power_rating_watts,door_is_open){

if(!missing(power_rating_watts)){

private$power_rating_watts

}

if(!missing(door_is_open)){

private$door_is_open

}

}

)

)

# Make a microwave

a_microwave_oven

power_rating_watts = 650,

door_is_open = TRUE

)

2.访问和设置私有域

private组件中的数据对用户隐藏,这是封装的原理。使用private$前缀可以访问私域(private field)。

存在active组件中的active binding(行为像变量的函数),可以获取和设置私有数据域。

Active bindings是R6中一种特殊的函数调用方式,把对函数的访问表现为对属性的访问,属于公有组件。

thing_factory

"Thing",

private = list(

..a_field = "a value"

),

active = list(

a_field = function(value) {

if(missing(value)) {

private$..a_field

} else {

assert_is_a_string(value) # or another assertion

private$..a_field

}

}

)

)

将active binding作为数据变量而不是函数进行调用。

a_thing

a_thing$a_field # not a_thing$a_field()

3、R6的继承

(1)子类的创建

继承将一个类(class)的功能复制到另一个。可在R6Class()中用inherit参数来创建子类。

child_class_factory

"ChildClass",

inherit = parent_class_factory

)

子类可以添加公有方法来扩展父类的功能,并在公有方法中使用前缀self$调用其他公有方法。

子类也可定义与父类相同的方法名称来重写该方法,用于扩展父类的功能,子类使用前缀super$访问父类的公有方法。

(2)跨级访问

R6类默认只能使用直接父类的功能。为了跨级访问,中间类(intermediate classes)首先需要定义一个active binding来显示父类,形式如下:

active = list(super_ = function() super)

然后可以跨级使用方法parent_method

(3)共享域

大部分类型的R变量是通过值复制,意思是当复制一个变量时 ,新的变量具有自己的复制值,改变其中一个变量不会影响另外一个。

环境变量(Environments)比较特殊,通过地址传送来复制(by reference),因此所有的复制品都是等同的,改变其中一个就会改变其他变量。R6类可利用环境的地址传送(by reference)复制行为在对象之间共享区域,定义一个名为shared的私域,方式如下:

创建一个新的环境,指定该环境的任意共享域,可通过active bindings访问。

工作方式与其他active bindings相同,但需使用private$shared$前缀来找回(retrieve)这些区域

R6Class(

"Thing",

private = list(

shared = {

e

e$a_shared_field

e

}

),

active = list(

a_shared_field = function(value) {

if(missing(value)) {

private$shared$a_shared_field

} else {

private$shared$a_shared_field

}

}

)

)

(4)R6对象的复制

R6对象使用与环境变量相同的地址传送复制方式,如果使用

a_reference_copy

R6 对象有一个自动生成的clone() 方法,用于值复制,使用clone()复制的对象的变化不影响其他对象。

a_value

当R6对象的一个或多个域包含另一个R6对象时,默认clone() 通过地址传送复制该R6域。

如果值复制这些R6域,clone() 方法必须使用参数:deep = TRUE。

a_deep_copy

(5)R6对象的消除

当消除对象时,定义公有finalize()方法运行自定义代码。该方法一般用于关闭与数据库或文件的连接,或者消除例如改变全局选项(option)或者图形参数的副作用。

thing_factory

"Thing",

public = list(

initialize = function(x, y, z) {

# do something

},

finalize = function() {

# undo something
# Print a message
"Disconnecting from the cooking times database."
# Disconnect from the database
dbDisconnect(private$conn)

}

)

) 

当R的自动垃圾回收器(automated garbage collector)从存储中清除对象时调用finalize() 方法,可使用gc()强制垃圾回收。

完 谢谢观看

分享

收藏

复制链接

新浪微博

微信扫一扫

mcem r语言代码_R语言面向对象编程:S3和R6相关推荐

  1. mcem r语言代码_R语言阈值自回归模型(TAR)代码示例

    原文链接: R语言时间序列TAR阈值模型分析​tecdat.cn 阈值模型用于统计的几个不同区域,而不仅仅是时间序列.一般的想法是,当变量的值超过某个阈值时,过程可能表现不同.也就是说,当值大于阈值时 ...

  2. mcem r语言代码_R语言关于if语句missing value where TRUEFALSE needed的错误

    apriori df #找出频繁候选1项集 for(i in 1:length(data)) for(j in 1:length(data[[i]])){ if(any(df$candidate == ...

  3. 协整检验r语言代码_R语言学习笔记(一):时间序列分析

    ARIMA(p,d,q)模型全称为差分自回归移动平均模型(Autoregressive Integrated Moving Average Model,简记ARIMA),AR是自回归, p为自回归项: ...

  4. 通过两个案例,从C语言过渡到Java面向对象编程

    ⭐欢迎来到JAVA语法专栏,一起学习,一起进步⭐ 金九银十秋招季,也是开学的时候,不少同学开了JAVA这门课.一起来看看这两个案例来熟悉熟悉吧. 一.案例来源 案例源自Java基础案例教程一书,现为学 ...

  5. Go语言基础之接口(面向对象编程下)

    1 接口 搜书 198200.com 1.1 接口介绍 接口(interface)是Go语言中核心部分,Go语言提供面向接口编程,那么接口是什么? 现实生活中,有许多接口的例子,比如说电子设备上的充电 ...

  6. r语言回归分析_R语言之cox回归分析

    Cox比例风险模型(Cox proportional-hazards model,也称为Cox回归),主要用于带有时间的生存结局的影响因素研究,或评价某个临床治疗措施对患者生存的影响. Cox模型可以 ...

  7. c语言中如何使用面向对象编程,如何使用C语言的面向对象

    我们都知道,C++才是面向对象的语言,但是C语言是否能使用面向对象的功能? (1)继承性 typedef struct _parent { int data_parent; }Parent; type ...

  8. 阿里Java学习路线:阶段 1:Java语言基础-Java面向对象编程:第30章:链表的定义与使用:课时145:综合实战:超市购物车(含完整代码)

    使用面向对象的概念表示出下面的生活场景:小明去超市买东西,所有买到的东西都放在了购物车之中,最后到收银台一起结账. (用购物车标准来降低耦合) 1.定义出一个商品的标准 interface IGood ...

  9. [C++程序语言设计笔记一]面向对象编程抽象,继承,重写基本介绍

    今天是个不错的日子,不仅有人收了我做徒弟从此传授我有关C++的一些知识,由于前一段时间喜欢上了外挂的研究也用到了一些MFC的知识及一些Windows APIs编程,但是对C++还是没有从根本上认识.我 ...

最新文章

  1. python 读取txt文件为字典_python将txt文件读取为字典的示例
  2. WEB请求处理六:浏览器HTTP协议漫谈
  3. SQL语句、PL/SQL语句、SQL*PLUS语句结束符号
  4. Java之文件流操作的文件读写
  5. 百度关键词抓取工具_VBA利用XMLHTTP抓取百度查询关键词结果的个数
  6. 常用加解密工具集合|视频图片加解密方案
  7. 算法十——深度优先搜索和广度优先搜索
  8. 【原】获取数据库(SQL SERVER 2005)的所有信息 Get all database information from SQL Server 2005 测试通过...
  9. (大数据工程师学习路径)第二步 Vim编辑器----Vim文档编辑
  10. python语言只采用解释一种翻译方式对吗_python与脚本语言
  11. Windows MongoDB安装配置
  12. 链表的相关面试题(完整)(C语言)
  13. 【底层原理】x86-64体系下一个奇怪问题的定位
  14. 哪个邮箱域名好?域名是永久的吗?
  15. 从零开始学习3D可视化之数据对接(2)
  16. 【OpenVINO 3】POT量化流程
  17. 使用Kali linux生成木马入侵局域网安卓手机
  18. 开始报名啦!——第二届融360“天机”金融风控大数据竞赛火热来袭
  19. 算法和刷题——二分法
  20. hive之生成唯一id

热门文章

  1. 农业农资产品英语词汇
  2. 二建 计算机辅助设计与制造,计算机辅助设计与制造
  3. 新版iTunesConnect应用撤销后重新上传二进制代码。
  4. 申请亚洲交友中心广告联盟教程
  5. Centos7.5-硬盘介绍和磁盘管理
  6. vue-org-tree 组织结构图组件应用及源码分析
  7. 有道云 markdown 生成目录的方法
  8. 基于ROS搭建简易软件框架实现ROV水下目标跟踪(补2)--水下slam仿真构想
  9. Table 标签详解
  10. ssh/scp断点续传rsync