前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >R语言面向对象_S4

R语言面向对象_S4

作者头像
火星娃统计
发布2021-11-02 15:01:10
4780
发布2021-11-02 15:01:10
举报
文章被收录于专栏:火星娃统计火星娃统计

R语言面向对象_S4

1. 概述

最近回头看了看以前写的一些数据处理,函数用的很多,总感觉有点力不从心,想想可能是没有面向对象的原因。虽然R6面向对象比较新,但是像Bioconductor社区的包都是基于S4,所以还是得学习这部分的内容。今天服务器搬家,闲着更新下公众号,不然都要废了

2. S4 对象

S4对象源自S3的发展,但是相比较S4对象定义更加严格,严格的定义,参数声明,继承等内容

2.1 S4对象的创建

代码语言:javascript
复制
setClass(class,representation,prototype,contains=character(),
  validity,access,where,version,sealed,package,
  S3methods=FALSE,slots)
  • class为类名
  • slots:定义属性和属性类型,此部分类似python的init
  • contains=character():定义父类,继承关系

2.1.1 实例化

代码语言:javascript
复制
# 定义对象
# 使用list将参数传递给slots
setClass("Person",slots=list(name="character",age="numeric"))

# 实例化对象

father <- new("Person",name="F",age=44)


father

# 显示创建了一个person的实例化对象father,其中
# father有两个属性,姓名和年龄
## An object of class "Person"
## Slot "name":
## [1] "F"
## 
## Slot "age":
## [1] 44
代码语言:javascript
复制
class(father)
## [1] "Person"
## attr(,"package")
## [1] ".GlobalEnv"
# 查看father对象为S4的对象
otype(father)# 此函数需要pryr包
## [1] "S4"

2.1.3 继承

代码语言:javascript
复制
# 创建一个S4对象Person
setClass("Person",slots=list(name="character",age="numeric"))

# 创建Person的子类定义属性father和mother
# contains表示并继承person
setClass("Son",slots=list(father="Person",mother="Person"),contains = "Person")

# 实例化Person对象,建立father和mother

father <- new("Person",name="F",age=44)
mother <- new("Person",name="M",age=39)

# 实例化一个Son对象命名为son
# 年龄为16,属性为father和mother
# son的类中其实并没有定义age和name,但是可以使用person的属性,也就是继承
son <- new("Son",name="S",age=16,father=father,mother=mother)

# 查看son对象的name属性
son@name
## [1] "S"
# 查看son对象的age属性
son@age
## [1] 16
# 查看son对象的father属性
son@father
## An object of class "Person"
## Slot "name":
## [1] "F"
## 
## Slot "age":
## [1] 44
# 查看son对象的mother属性
son@mother
## An object of class "Person"
## Slot "name":
## [1] "M"
## 
## Slot "age":
## [1] 39
# 查看son类型
otype(son)
## [1] "S4"
# 查看son@name的属性
otype(son@name)
## [1] "base"
#  查看son@mother的属性
otype(son@mother)
## [1] "S4"
# 用isS4()检查S4对象的类型
isS4(son)
## [1] TRUE
isS4(son@name)
## [1] FALSE
isS4(son@mother)
## [1] TRUE

2.1.4 prototype定义属性默认值

代码语言:javascript
复制
setClass("Person",slots=list(name="character",age="numeric"))

# 属性age为空
a <- new("Person",name="a")
a
## An object of class "Person"
## Slot "name":
## [1] "a"
## 
## Slot "age":
## numeric(0)
# 设置属性age的默认值为20

setClass("Person",slots=list(name="character",age="numeric"),prototype=list(age=20))

# 初始化b对象
b <- new("Person",name="b")

# 属性age的默认值是20
b 
## An object of class "Person"
## Slot "name":
## [1] "b"
## 
## Slot "age":
## [1] 20

2.1.5 类型检查

代码语言:javascript
复制
setClass("Person",slots=list(name="character",age="numeric"))
#传入错误age类型
# numeric 为数字类型
bad <- new("Person",name="bad",age="abc")

###
#Error in validObject(.Object) : 类别为“Person”的对象不对: invalid object for slot "age" in class "Person": got class "character", should be or extend class "numeric"       
# 设置age的非负检查
setValidity("Person",function(object){
  if(object@age <= 0) stop("Age is negative.")
})

# 传入小于0的年龄
bad2 <- new("Person",name="bad",age=-1)

###
Error in validityMethod(object) : Age is negative.

2.1.6 从一个已经实例化的对象中创建新对象

S4对象,还支持从一个已经实例化的对象中创建新对象,创建时可以覆盖旧对象的值

代码语言:javascript
复制
setClass("Person",slots=list(name="character",age="numeric"))

# 创建一个对象实例n1

n1 <- new("Person",name="n1",age=19)
n1
## An object of class "Person"
## Slot "name":
## [1] "n1"
## 
## Slot "age":
## [1] 19

# 从实例n1中,创建实例n2,并修改name的属性值
n2 <- initialize(n1,name="n2")
n2
## An object of class "Person"
## Slot "name":
## [1] "n2"
## 
## Slot "age":
## [1] 19

2.2 使用@访问对象属性

代码语言:javascript
复制
setClass("Person",slots=list(name="character",age="numeric"))
a <- new("Person",name="a")

# 访问S4对象的属性

a@name
## [1] "a"
slot(a,"name")
## [1] "a"
# 错误的访问
#a$name
#a[1]

2.3 S4的泛型函数

  • 普通函数的定义和调用
代码语言:javascript
复制
work <- function(x) cat(x,"is working")
work("Conan")
## Conan is working
  • S4的方式将定义与实现分离
代码语言:javascript
复制
# 定义数据对象类型
setClass("Person",slots=list(name="character",age="numeric"))
# 定义接口函数
setGeneric("work",function(object) standardGeneric("work"))
## [1] "work"
# 定义实现函数
setMethod("work",signature(object="Person"),function(object) cat(object@name,"is working"))
## [1] "work"
# 实例化对象person
a <- new("Person",name="Conan",age=16)

# 将数据对象通过接口函数传入
work(a)
## Conan is working

2.4 查看S4对象的函数

当我们使用S4对象进行面向对象封装后,我们还需要能查看到S4对象的定义和函数定义,

代码语言:javascript
复制
library(pryr)
# 检查work的类型
ftype(work)
# [1] "s4"      "generic"
# 直接查看work函数
work
#standardGeneric for "work" defined from package ".GlobalEnv"
#
#function (object) 
#standardGeneric("work")
#<environment: 0x000001d98cf9fad8>
#Methods may be defined for arguments: object
#Use  showMethods("work")  for currently available ones.
# 查看work函数的显示定义
showMethods(work)
#Function: work (package .GlobalEnv)
#object="Person"
# 查看Person对象的work函数现实
getMethod("work","Person")
#Method Definition:
#
#function (object) 
#cat(object@name, "is working")
#
#Signatures:
#        object  
#target  "Person"
#defined "Person"

# 检查Person对象有没有work函数
existMethod("work","Person")
hasMethod("work","Person")

2.6 示例

研发一个数据处理程序

代码语言:javascript
复制
setClass("check",slots=list(name="character"))

# 定义check_na类,并继承check,

setClass("check_na",contains = "check",slots=list(x="numeric"))

car_na <- new("check_na",name="car_na",x=mtcars$mpg)
iris_na <- new ("check_na",name="iris_na",x=iris$Sepal.Width)

#定义接口
setGeneric("do",function(obj,...){
  standardGeneric("do")
})
setMethod("do","check_na",function(obj,...){
  print("看看有多少缺失")
  sum(is.na(obj@x))
})

do(car_na)
do(iris_na)
#[1] "看看有多少缺失"
#[1] 0

3. 结束语

这不是我想要的东西,S4对象不再研究

考虑重新用R6

love & peace

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-10-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 火星娃统计 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • R语言面向对象_S4
    • 1. 概述
      • 2. S4 对象
        • 2.1 S4对象的创建
        • 2.1.1 实例化
        • 2.1.3 继承
        • 2.1.4 prototype定义属性默认值
        • 2.1.5 类型检查
        • 2.1.6 从一个已经实例化的对象中创建新对象
      • 2.2 使用@访问对象属性
        • 2.3 S4的泛型函数
          • 2.4 查看S4对象的函数
            • 2.6 示例
              • 3. 结束语
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档