前言

本文接上一篇文章 R语言基于S3的面向对象编程,本文继续介绍R语言基于S4的面向对象编程。

S4对象系统具有明显的结构化特征,更适合面向对象的程序设计。Bioconductor社区,以S4对象系统做为基础架构,只接受符合S4定义的R包。

目录

  1. S4对象介绍
  2. 创建S4对象
  3. 访问对象的属性
  4. S4的泛型函数
  5. 查看S4对象的函数
  6. S4对象的使用

1 S4对象介绍

S4对象系统是一种标准的R语言面向对象实现方式,S4对象有明确的类定义,参数定义,参数检查,继承关系,实例化等的面向对象系统的特征。

2 创建S4对象

本文的系统环境

  • Linux: Ubuntu Server 12.04.2 LTS 64bit
  • R: 3.0.1 x86_64-pc-linux-gnu

为了方便我们检查对象的类型,引入pryr包作为辅助工具。关于pryr包的介绍,请参考文章:[撬动R内核的高级工具包pryr](http://blog.fens.me/r-pryr/)


  1. # 加载pryr包
  2. > library(pryr)

2.1 如何创建S4对象?

由于S4对象是标准的面向对象实现方式, 有专门的类定义函数 setClass() 和类的实例化函数new() ,我们看一下setClass()和new()是如何动作的。

2.1.1 setClass()

查看setClass的函数定义


  1. setClass(Class, representation, prototype, contains=character(),
  2. validity, access, where, version, sealed, package,
  3. S3methods = FALSE, slots)

参数列表:

  • 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以后不建议使用

2.2 创建一个S4对象实例


  1. # 定义一个S4对象
  2. > setClass("Person",slots=list(name="character",age="numeric"))
  3. # 实例化一个Person对象
  4. > father<-new("Person",name="F",age=44)
  5. # 查看father对象,有两个属性name和age
  6. > father
  7. An object of class "Person"
  8. Slot "name":
  9. [1] "F"
  10. Slot "age":
  11. [1] 44
  12. # 查看father对象类型,为Person
  13. > class(father)
  14. [1] "Person"
  15. attr(,"package")
  16. [1] ".GlobalEnv"
  17. # 查看father对象为S4的对象
  18. > otype(father)
  19. [1] "S4"

2.3 创建一个有继承关系的S4对象


  1. # 创建一个S4对象Person
  2. > setClass("Person",slots=list(name="character",age="numeric"))
  3. # 创建Person的子类
  4. > setClass("Son",slots=list(father="Person",mother="Person"),contains="Person")
  5. # 实例化Person对象
  6. > father<-new("Person",name="F",age=44)
  7. > mother<-new("Person",name="M",age=39)
  8. # 实例化一个Son对象
  9. > son<-new("Son",name="S",age=16,father=father,mother=mother)
  10. # 查看son对象的name属性
  11. > son@name
  12. [1] "S"
  13. # 查看son对象的age属性
  14. > son@age
  15. [1] 16
  16. # 查看son对象的father属性
  17. > son@father
  18. An object of class "Person"
  19. Slot "name":
  20. [1] "F"
  21. Slot "age":
  22. [1] 44
  23. # 查看son对象的mother属性
  24. > slot(son,"mother")
  25. An object of class "Person"
  26. Slot "name":
  27. [1] "M"
  28. Slot "age":
  29. [1] 39
  30. # 检查son类型
  31. > otype(son)
  32. [1] "S4"
  33. # 检查son@name属性类型
  34. > otype(son@name)
  35. [1] "primitive"
  36. # 检查son@mother属性类型
  37. > otype(son@mother)
  38. [1] "S4"
  39. # 用isS4(),检查S4对象的类型
  40. > isS4(son)
  41. [1] TRUE
  42. > isS4(son@name)
  43. [1] FALSE
  44. > isS4(son@mother)
  45. [1] TRUE

2.4 S4对象的默认值


  1. > setClass("Person",slots=list(name="character",age="numeric"))
  2. # 属性age为空
  3. > a<-new("Person",name="a")
  4. > a
  5. An object of class "Person"
  6. Slot "name":
  7. [1] "a"
  8. Slot "age":
  9. numeric(0)
  10. # 设置属性age的默认值20
  11. > setClass("Person",slots=list(name="character",age="numeric"),prototype = list(age = 20))
  12. # 属性age为空
  13. > b<-new("Person",name="b")
  14. # 属性age的默认值是20
  15. > b
  16. An object of class "Person"
  17. Slot "name":
  18. [1] "b"
  19. Slot "age":
  20. [1] 20

2.5 S4对象的类型检查


  1. > setClass("Person",slots=list(name="character",age="numeric"))
  2. # 传入错误的age类型
  3. > bad<-new("Person",name="bad",age="abc")
  4. Error in validObject(.Object) :
  5. invalid class Person object: invalid object for slot "age" in class "Person": got class "character", should be or extend class "numeric"
  6. # 设置age的非负检查
  7. > setValidity("Person",function(object) {
  8. + if (object@age <= 0) stop("Age is negative.")
  9. + })
  10. Class "Person" [in ".GlobalEnv"]
  11. Slots:
  12. Name: name age
  13. Class: character numeric
  14. # 修传入小于0的年龄
  15. > bad2<-new("Person",name="bad",age=-1)
  16. Error in validityMethod(object) : Age is negative.

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

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


  1. > setClass("Person",slots=list(name="character",age="numeric"))
  2. # 创建一个对象实例n1
  3. > n1<-new("Person",name="n1",age=19);n1
  4. An object of class "Person"
  5. Slot "name":
  6. [1] "n1"
  7. Slot "age":
  8. [1] 19
  9. # 从实例n1中,创建实例n2,并修改name的属性值
  10. > n2<-initialize(n1,name="n2");n2
  11. An object of class "Person"
  12. Slot "name":
  13. [1] "n2"
  14. Slot "age":
  15. [1] 19

3 访问对象的属性

在S3对象中,一般我使用$来访问一个对象的属性,但在S4对象中,我们只能使用@来访问一个对象的属性


  1. > setClass("Person",slots=list(name="character",age="numeric"))
  2. > a<-new("Person",name="a")
  3. # 访问S4对象的属性
  4. > a@name
  5. [1] "a"
  6. > slot(a, "name")
  7. [1] "a"
  8. # 错误的属性访问
  9. > a$name
  10. Error in a$name : $ operator not defined for this S4 class
  11. > a[1]
  12. Error in a[1] : object of type 'S4' is not subsettable
  13. > a[[1]]
  14. Error in a[[1]] : this S4 class is not subsettable

4 S4的泛型函数

S4的泛型函数实现有别于S3的实现,S4分离了方法的定义和实现,如在其他语言中我们常说的接口和实现分离。通过setGeneric()来定义接口,通过setMethod()来定义现实类。这样可以让S4对象系统,更符合面向对象的特征。

普通函数的定义和调用


  1. > work<-function(x) cat(x, "is working")
  2. > work('Conan')
  3. Conan is working

让我来看看如何用R分离接口和现实


  1. # 定义Person对象
  2. > setClass("Person",slots=list(name="character",age="numeric"))
  3. # 定义泛型函数work,即接口
  4. > setGeneric("work",function(object) standardGeneric("work"))
  5. [1] "work"
  6. # 定义work的现实,并指定参数类型为Person对象
  7. > setMethod("work", signature(object = "Person"), function(object) cat(object@name , "is working") )
  8. [1] "work"
  9. # 创建一个Person对象a
  10. > a<-new("Person",name="Conan",age=16)
  11. # 把对象a传入work函数
  12. > work(a)
  13. Conan is working

通过S4对象系统,把原来的函数定义和调用2步,为成了4步进行:

  • 定义数据对象类型
  • 定义接口函数
  • 定义实现函数
  • 把数据对象以参数传入到接口函数,执行实现函数

通过S4对象系统,是一个结构化的,完整的面向对象实现。

5 查看S4对象的函数

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

还以上节中Person和work的例子


  1. # 检查work的类型
  2. > ftype(work)
  3. [1] "s4" "generic"
  4. # 直接查看work函数
  5. > work
  6. standardGeneric for "work" defined from package ".GlobalEnv"
  7. function (object)
  8. standardGeneric("work")
  9. <environment: 0x2aa6b18>
  10. Methods may be defined for arguments: object
  11. Use showMethods("work") for currently available ones.
  12. # 查看work函数的现实定义
  13. > showMethods(work)
  14. Function: work (package .GlobalEnv)
  15. object="Person"
  16. # 查看Person对象的work函数现实
  17. > getMethod("work", "Person")
  18. Method Definition:
  19. function (object)
  20. cat(object@name, "is working")
  21. Signatures:
  22. object
  23. target "Person"
  24. defined "Person"
  25. > selectMethod("work", "Person")
  26. Method Definition:
  27. function (object)
  28. cat(object@name, "is working")
  29. Signatures:
  30. object
  31. target "Person"
  32. defined "Person"
  33. # 检查Person对象有没有work函数
  34. > existsMethod("work", "Person")
  35. [1] TRUE
  36. > hasMethod("work", "Person")
  37. [1] TRUE

6 S4对象的使用

我们接下用S4对象做一个例子,定义一组图形函数的库。

6.1 任务一:定义图形库的数据结构和计算函数

假设最Shape为图形的基类,包括圆形(Circle)和椭圆形(Ellipse),并计算出它们的面积(area)和周长(circum)。

  • 定义图形库的数据结构
  • 定义圆形的数据结构,并计算面积和周长
  • 定义椭圆形的数据结构,并计算面积和周长

如图所示结构:

定义基类Shape 和 圆形类Circle


  1. # 定义基类Shape
  2. > setClass("Shape",slots=list(name="character"))
  3. # 定义圆形类Circle,继承Shape,属性radius默认值为1
  4. > setClass("Circle",contains="Shape",slots=list(radius="numeric"),prototype=list(radius = 1))
  5. # 验证radius属性值要大等于0
  6. > setValidity("Circle",function(object) {
  7. + if (object@radius <= 0) stop("Radius is negative.")
  8. + })
  9. Class "Circle" [in ".GlobalEnv"]
  10. Slots:
  11. Name: radius name
  12. Class: numeric character
  13. Extends: "Shape"
  14. # 创建两个圆形实例
  15. > c1<-new("Circle",name="c1")
  16. > c2<-new("Circle",name="c2",radius=5)

定义计算面积的接口和现实


  1. # 计算面积泛型函数接口
  2. > setGeneric("area",function(obj,...) standardGeneric("area"))
  3. [1] "area"
  4. # 计算面积的函数现实
  5. > setMethod("area","Circle",function(obj,...){
  6. + print("Area Circle Method")
  7. + pi*obj@radius^2
  8. + })
  9. [1] "area"
  10. # 分别计算c1和c2的两个圆形的面积
  11. > area(c1)
  12. [1] "Area Circle Method"
  13. [1] 3.141593
  14. > area(c2)
  15. [1] "Area Circle Method"
  16. [1] 78.53982

定义计算周长的接口和现实


  1. # 计算周长泛型函数接口
  2. > setGeneric("circum",function(obj,...) standardGeneric("circum"))
  3. [1] "circum"
  4. # 计算周长的函数现实
  5. > setMethod("circum","Circle",function(obj,...){
  6. + 2*pi*obj@radius
  7. + })
  8. # 分别计算c1和c2的两个圆形的面积
  9. [1] "circum"
  10. > circum(c1)
  11. [1] 6.283185
  12. > circum(c2)
  13. [1] 31.41593

上面的代码,我们实现了圆形的定义,下来我们实现椭圆形。


  1. # 定义椭圆形的类,继承Shape,radius参数默认值为c(1,1),分别表示椭圆形的长半径和短半径
  2. > setClass("Ellipse",contains="Shape",slots=list(radius="numeric"),prototype=list(radius=c(1,1)))
  3. # 验证radius参数
  4. > setValidity("Ellipse",function(object) {
  5. + if (length(object@radius) != 2 ) stop("It's not Ellipse.")
  6. + if (length(which(object@radius<=0))>0) stop("Radius is negative.")
  7. + })
  8. Class "Ellipse" [in ".GlobalEnv"]
  9. Slots:
  10. Name: radius name
  11. Class: numeric character
  12. Extends: "Shape"
  13. # 创建两个椭圆形实例e1,e2
  14. > e1<-new("Ellipse",name="e1")
  15. > e2<-new("Ellipse",name="e2",radius=c(5,1))
  16. # 计算椭圆形面积的函数现实
  17. > setMethod("area", "Ellipse",function(obj,...){
  18. + print("Area Ellipse Method")
  19. + pi * prod(obj@radius)
  20. + })
  21. [1] "area"
  22. # 计算e1,e2两个椭圆形的面积
  23. > area(e1)
  24. [1] "Area Ellipse Method"
  25. [1] 3.141593
  26. > area(e2)
  27. [1] "Area Ellipse Method"
  28. [1] 15.70796
  29. # 计算椭圆形周长的函数现实
  30. > setMethod("circum","Ellipse",function(obj,...){
  31. + cat("Ellipse Circum :\n")
  32. + 2*pi*sqrt((obj@radius[1]^2+obj@radius[2]^2)/2)
  33. + })
  34. [1] "circum"
  35. # 计算e1,e2两个椭圆形的周长
  36. > circum(e1)
  37. Ellipse Circum :
  38. [1] 6.283185
  39. > circum(e2)
  40. Ellipse Circum :
  41. [1] 22.65435

6.2 任务二:重构圆形和椭圆形的设计

上一步,我们已经完成了 圆形和椭圆形 的数据结构定义,以及计算面积和周长的方法现实。不知大家有没有发现,圆形是椭圆形的一个特例呢?

当椭圆形的长半径和短半径相等时,即radius的两个值相等,形成的图形为圆形。利用这个特点,我们就可以重新设计 圆形和椭圆形 的关系。椭圆形是圆形的父类,而圆形是椭圆形的子类。

如图所示结构:


  1. # 基类Shape
  2. > setClass("Shape",slots=list(name="character",shape="character"))
  3. # Ellipse继承Shape
  4. > setClass("Ellipse",contains="Shape",slots=list(radius="numeric"),prototype=list(radius=c(1,1),shape="Ellipse"))
  5. # Circle继承Ellipse
  6. > setClass("Circle",contains="Ellipse",slots=list(radius="numeric"),prototype=list(radius = 1,shape="Circle"))
  7. # 定义area接口
  8. > setGeneric("area",function(obj,...) standardGeneric("area"))
  9. [1] "area"
  10. # 定义area的Ellipse实现
  11. > setMethod("area","Ellipse",function(obj,...){
  12. + cat("Ellipse Area :\n")
  13. + pi * prod(obj@radius)
  14. + })
  15. [1] "area"
  16. # 定义area的Circle实现
  17. > setMethod("area","Circle",function(obj,...){
  18. + cat("Circle Area :\n")
  19. + pi*obj@radius^2
  20. + })
  21. [1] "area"
  22. # 定义circum接口
  23. > setGeneric("circum",function(obj,...) standardGeneric("circum"))
  24. [1] "circum"
  25. # 定义circum的Ellipse实现
  26. > setMethod("circum","Ellipse",function(obj,...){
  27. + cat("Ellipse Circum :\n")
  28. + 2*pi*sqrt((obj@radius[1]^2+obj@radius[2]^2)/2)
  29. + })
  30. [1] "circum"
  31. # 定义circum的Circle实现
  32. > setMethod("circum","Circle",function(obj,...){
  33. + cat("Circle Circum :\n")
  34. + 2*pi*obj@radius
  35. + })
  36. [1] "circum"
  37. # 创建实例
  38. > e1<-new("Ellipse",name="e1",radius=c(2,5))
  39. > c1<-new("Circle",name="c1",radius=2)
  40. # 计算椭圆形的面积和周长
  41. > area(e1)
  42. Ellipse Area :
  43. [1] 31.41593
  44. > circum(e1)
  45. Ellipse Circum :
  46. [1] 23.92566
  47. # 计算圆形的面积和周长
  48. > area(c1)
  49. Circle Area :
  50. [1] 12.56637
  51. > circum(c1)
  52. Circle Circum :
  53. [1] 12.56637

我们重构后的结构,是不是会更合理呢!!

6.3 任务三:增加矩形的图形处理

我们的图形库,进一步扩充,需要加入矩形和正方形。

  • 定义矩形的数据结构,并计算面积和周长
  • 定义正方形的数据结构,并计算面积和周长
  • 正方形是矩形的特例,定义矩形是正方形的父类,而正方形是矩形的子类。

如图所示结构:


  1. # 定义矩形Rectangle,继承Shape
  2. > setClass("Rectangle",contains="Shape",slots=list(edges="numeric"),prototype=list(edges=c(1,1),shape="Rectangle"))
  3. # 定义正方形Square,继承Rectangle
  4. > setClass("Square",contains="Rectangle",slots=list(edges="numeric"),prototype=list(edges=1,shape="Square"))
  5. # 定义area的Rectangle实现
  6. > setMethod("area","Rectangle",function(obj,...){
  7. + cat("Rectangle Area :\n")
  8. + prod(obj@edges)
  9. + })
  10. [1] "area"
  11. # 定义area的Square实现
  12. > setMethod("area","Square",function(obj,...){
  13. + cat("Square Area :\n")
  14. + obj@edges^2
  15. + })
  16. [1] "area"
  17. # 定义circum的Rectangle实现
  18. > setMethod("circum","Rectangle",function(obj,...){
  19. + cat("Rectangle Circum :\n")
  20. + 2*sum(obj@edges)
  21. + })
  22. [1] "circum"
  23. # 定义circum的Square实现
  24. > setMethod("circum","Square",function(obj,...){
  25. + cat("Square Circum :\n")
  26. + 4*obj@edges
  27. + })
  28. [1] "circum"
  29. # 创建实例
  30. > r1<-new("Rectangle",name="r1",edges=c(2,5))
  31. > s1<-new("Square",name="s1",edges=2)
  32. # 计算矩形形的面积和周长
  33. > area(r1)
  34. Rectangle Area :
  35. [1] 10
  36. > area(s1)
  37. Square Area :
  38. [1] 4
  39. # 计算正方形的面积和周长
  40. > circum(r1)
  41. Rectangle Circum :
  42. [1] 14
  43. > circum(s1)
  44. Square Circum :
  45. [1] 8

这样,我们的图形库,已经支持了4种图形了!用面向对象的结构来设计,是不是结构化思路很清晰呢!!

6.4 任务四:在基类Shape中,增加shape属性和getShape方法

接下来,要对图形库的所有图形,定义图形类型的变量shape,然后再提供一个getShape函数可以检查实例中的是shape变量。

这个需求,如果没有面向对象的结构,那么你需要在所有图形定义的代码中,都增加一个参数和一个判断,如果有100图形,改起来还是挺复杂的。而面向对象的程序设计,就非常容易解决这个需求。我们只需要在基类上改动代码就可以实现了。

如图所示结构:


  1. # 重新定义基类Shape,增加shape属性
  2. > setClass("Shape",slots=list(name="character",shape="character"))
  3. # 定义getShape接口
  4. > setGeneric("getShape",function(obj,...) standardGeneric("getShape"))
  5. [1] "getShape"
  6. # 定义getShape实现
  7. > setMethod("getShape","Shape",function(obj,...){
  8. + cat(obj@shape,"\n")
  9. + })
  10. [1] "getShape"

其实,这样改动一个就可以了,我们只需要重实例化每个图形的对象就行了。


  1. # 实例化一个Square对象,并给shape属性赋值
  2. > s1<-new("Square",name="s1",edges=2, shape="Square")
  3. # 调用基类的getShape()函数
  4. > getShape(r1)
  5. Rectangle

是不是很容易的呢!在代码只在基类里修改了,所有的图形就有了对应的属性和方法。

如果我们再多做一步,可以修改每个对象的定义,增加shape属性的默认值。


  1. setClass("Ellipse",contains="Shape",slots=list(radius="numeric"),prototype=list(radius=c(1,1),shape="Ellipse"))
  2. setClass("Circle",contains="Ellipse",slots=list(radius="numeric"),prototype=list(radius = 1,shape="Circle"))
  3. setClass("Rectangle",contains="Shape",slots=list(edges="numeric"),prototype=list(edges=c(1,1),shape="Rectangle"))
  4. setClass("Square",contains="Rectangle",slots=list(edges="numeric"),prototype=list(edges=1,shape="Square"))

再实例化对象时,属性shape会被自动赋值


  1. # 实例化一个Square对象
  2. > s1<-new("Square",name="s1",edges=2)
  3. # 调用基类的getShape()函数
  4. > getShape(r1)
  5. Rectangle

下面是完整的R语言的代码实现:


  1. setClass("Shape",slots=list(name="character",shape="character"))
  2. setClass("Ellipse",contains="Shape",slots=list(radius="numeric"),prototype=list(radius=c(1,1),shape="Ellipse"))
  3. setClass("Circle",contains="Ellipse",slots=list(radius="numeric"),prototype=list(radius = 1,shape="Circle"))
  4. setClass("Rectangle",contains="Shape",slots=list(edges="numeric"),prototype=list(edges=c(1,1),shape="Rectangle"))
  5. setClass("Square",contains="Rectangle",slots=list(edges="numeric"),prototype=list(edges=1,shape="Square"))
  6. setGeneric("getShape",function(obj,...) standardGeneric("getShape"))
  7. setMethod("getShape","Shape",function(obj,...){
  8. cat(obj@shape,"\n")
  9. })
  10. setGeneric("area",function(obj,...) standardGeneric("area"))
  11. setMethod("area","Ellipse",function(obj,...){
  12. cat("Ellipse Area :\n")
  13. pi * prod(obj@radius)
  14. })
  15. setMethod("area","Circle",function(obj,...){
  16. cat("Circle Area :\n")
  17. pi*obj@radius^2
  18. })
  19. setMethod("area","Rectangle",function(obj,...){
  20. cat("Rectangle Area :\n")
  21. prod(obj@edges)
  22. })
  23. setMethod("area","Square",function(obj,...){
  24. cat("Square Area :\n")
  25. obj@edges^2
  26. })
  27. setGeneric("circum",function(obj,...) standardGeneric("circum"))
  28. setMethod("circum","Ellipse",function(obj,...){
  29. cat("Ellipse Circum :\n")
  30. 2*pi*sqrt((obj@radius[1]^2+obj@radius[2]^2)/2)
  31. })
  32. setMethod("circum","Circle",function(obj,...){
  33. cat("Circle Circum :\n")
  34. 2*pi*obj@radius
  35. })
  36. setMethod("circum","Rectangle",function(obj,...){
  37. cat("Rectangle Circum :\n")
  38. 2*sum(obj@edges)
  39. })
  40. setMethod("circum","Square",function(obj,...){
  41. cat("Square Circum :\n")
  42. 4*obj@edges
  43. })
  44. e1<-new("Ellipse",name="e1",radius=c(2,5))
  45. c1<-new("Circle",name="c1",radius=2)
  46. r1<-new("Rectangle",name="r1",edges=c(2,5))
  47. s1<-new("Square",name="s1",edges=2)
  48. area(e1)
  49. area(c1)
  50. circum(e1)
  51. circum(c1)
  52. area(r1)
  53. area(s1)
  54. circum(r1)
  55. circum(s1)

通过这个例子,我们全面地了解了R语言中面向对象的使用,和S4对象系统的面向对象程序设计!

在程序员的世界里,世间万物都可以抽象成对象。

http://blog.fens.me/r-class-s4/

R语言基于S4的面向对象编程的更多相关文章

  1. go语言之进阶篇面向对象编程

    1.面向对象编程 对于面向对象编程的支持Go 语言设计得非常简洁而优雅.因为, Go语言并没有沿袭传统面向对象编程中的诸多概念,比如继承(不支持继承,尽管匿名字段的内存布局和行为类似继承,但它并不是继 ...

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

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

  3. Go语言——没有对象的面向对象编程

    本文译自Steve Francia在OSCON 2014的一个PPT,原作请前往:https://spf13.com/presentation/go-for-object-oriented-progr ...

  4. javascript: 基于原型的面向对象编程

    Douglas Crockford指出javascript是世界上最被误解的编程语言.由于javascript缺少常见的面向对象概念,许多程序猿认为javascript不是一个合适的语言.我在做第一个 ...

  5. 吴裕雄--天生自然 R语言开发学习:高级编程

    运行的条件是一元逻辑向量(TRUE或FALSE)并且不能有缺失(NA).else部分是可选的.如果 仅有一个语句,花括号也是可以省略的. 下面的代码片段是一个例子: plot(x, y) } else ...

  6. R语言处理大规模数据集的编程要点

    1.提高程序效率,保证执行速度 (1)尽量使用向量化运算 (2)尽量使用矩阵,必要时才使用数据框 (3)使用read.table时,尽量显式设定colClasses和nrows,设定comment.c ...

  7. Rserve详解,R语言客户端RSclient【转】

    R语言服务器程序 Rserve详解 http://blog.fens.me/r-rserve-server/ Rserve的R语言客户端RSclient https://blog.csdn.net/u ...

  8. 比较分析C++、Java、Python、R语言的面向对象特征,这些特征如何实现的?有什么相同点?

    一门课的课后题答案,在这里备份一下: 面向对象程序设计语言 –  比较分析C++.Java.Python.R语言的面向对象特征,这些特征如何实现的?有什么相同点? C++ 语言的面向对象特征: 对象模 ...

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

    一.基于S3的面向对象编程 基于S3的面向对象编程是一种基于泛型函数(generic function)的实现方式. 1.S3函数的创建 S3对象组成:generic(generic FUN)+met ...

随机推荐

  1. WCF与WPF

    1. WCF(Windows Communication Foundation )是一个统一的,可用于建立安全,可靠的面向服务的应用高效的开发平台.WCF是构建安全可靠的事务性服务的统一框架.它是一种 ...

  2. ASM_Oracle ASM的常用命令(汇总)

    2014-07-02 Created By BaoXinjian

  3. 【转载】BasicDataSource配置说明

    commons DBCP 配置参数简要说明 在配置时,主要难以理解的主要有:removeAbandoned .logAbandoned.removeAbandonedTimeout.maxWait这四 ...

  4. 群智能优化算法-测试函数matlab源码

    群智能优化算法测试函数matlab源代码 global M; creatematrix(2); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %画ackley图. %%%% ...

  5. mysql-5.7 扩展innodb系统表空间详解

    一.innodb系统表空间的简介: innodb 系统表空间是由若干个文件组成的,表空间的大小就是对应文件的大小,表空间文件是由innodb_data_file_path 这人参数来定义的.下面我们来 ...

  6. find命令之exec和xargs

    exec: find是我们很常用的一个Linux命令,但是我们一般查找出来的并不仅仅是看看而已,还会有进一步的操作,这个时候exec的作用就显现出来了. exec解释: -exec  参数后面跟的是c ...

  7. JS格式化数字保留两位小数点示例代码

    格式化数字保留两位小数点实现的方法有很多,在接下来的文章中将为大家详细介绍下如何使用js来实现 a = a.toFixed(2);//保留2位但结果为一个String类型 a = parseFloat ...

  8. 转:python常用运维脚本实例

    python常用运维脚本实例 转载  file是一个类,使用file('file_name', 'r+')这种方式打开文件,返回一个file对象,以写模式打开文件不存在则会被创建.但是更推荐使用内置函 ...

  9. redis make test 报错

    [root@ok redis-]# make test cd src && make test make[]: Entering directory `/usr/local/src/r ...

  10. C# RSA数据加密

    第一步产生密钥类 CreateKey using System; using System.Collections.Generic; using System.Linq; using System.T ...