浅谈R语言中OOP编程方法

时间:2022-06-26 03:49:46

浅谈R语言中OOP编程方法

摘要:R作为统计领域广泛使用的一种统计软件,具有开源、免费、灵活的诸多优点,编程语言强大,但用到面向对象的编程方法却不多。本文通过对R中面向对象编程的研究,使读者进一步的了解R软件。

关键词:R软件;OOP;泛型函数;类和方法

中图分类号:TP312文献标识码:A文章编号:1007-9599 (2011) 16-0000-02

OOP Programming in the R Language

Bai Yangchun1,Hu Rongxing2,Deng Yongchao1

(1.Sichuan Police College,Luzhou646000,China;2. Meishan Central Branch of the People's Bank of China,Meishan620010,China)

Abstract:R is a kind of statistical software widely used as a statistical areas,it has many advantages,such as open source,free,flexible,the programming language is power,but it rarely use object-oriented programming.The paper is a research on R about object-oriented programming in order to let the reader have a better understanding of R software.

Keywords:R software;OOP;Generic function;Classes and methods

一、引言

R是一套完整的数据处理、计算和制图软件系统。其功能包括:数据存储和处理系统;数组运算工具;完整连贯的统计分析工具;优秀的统计制图功能;简便而强大的编程语言:可操纵数据的输入和输入,可实现分支、循环,用户可自定义功能。R主要面向统计计算,似乎很少会用到面向对象的编程方法。但在实际的统计计算中,比如当需要用一种新的方式来表示数据,该方式与已有的数据类型有区别的时候或者当需要一个新的函数,该函数可以根据不同的参数类型做出不同的反应的时候,使用面向对象的编程方法可以使编程更有效率。

二、面向对象的R

在R中可能经常需要定义一个新的函数,相反较少去定义一个新的类。但有时候定义一个类是一个很关键的步骤。一个类通常决定了如何对对象进行处理,决定了对象中应当包含什么样的信息。R的OOP方式基于泛型函数(generic function),而不是基于类层次结构。不过R的方式仍然是单一分派方式,与C++、Java等“传统”语言相同。

R可以进行完全面向对象的编程,但是面向对象并不只限于一种模型。OOP其实并不一定意味着继承,而是一般的分派决策。换言之,在传统OOP语言中的obj.method()调用会通过对象的方法分析次序寻找“第一个”具有.method()方法的obj祖先类。R并不用一系列类来定义和覆盖各种方法,而是创建一系列泛型函数,这些函数带有一个标记,指出它们应该在什么类型的对象上进行操作。

(一)泛型函数

那么到底什么是R中的泛型函数?R中的面向对象又是怎么样的呢?我们首先看下面这样的一个简单的实例[1],创建一个泛型函数whoAmI()以及一些要被分派标记的方法。

>whoami

>whoami.foo

>whoami.bar

>whoami.default

这里我们要注意R中的每个对象可能属于零个、一个或多个类。具体地说,任何给定对象的MRO仅仅是class属性中的命名类向量。我们可以用class()函数查看对象所属的类。在创建了泛型函数和类之后,R中的泛型函数是如何工作如图1[5]所示。

图1 泛型函数的工作情况

从上面的例子我们可以看出,如果每个类本身都是一个对象,那么更接近基于原型的OOP系统而不是基于类的系统。R中的“面向对象”是以类和泛型函数为基础,类可以多重继承类,泛型函数可以分派到任意的参数集合,泛型函数将不同的方法聚集到一起,由R根据函数的对象的类型来决定选择执行哪个方法。在某些情况下,类和方法是不同的概念要区别对待。

(二)类和虚类

类(Class)表示对现实生活中一类具有共同特征的事物的抽象,是面向对象编程的基础。我们用setClass来定义一个类。

setClass(Class,representation,prototype,contains=character(),

validity,access,where=1,version=FALSE0)

定义了一个类后,就可以用函数new()来生成一个类的实例(instances)。类定义了一个对象的结构。类的实例代表了对象本身。一个子类是对其父类的扩展,一个新的类将包含其父类的所有接口。在创建一个新的类时,接口的名字不能重复(包括其直接或间接的父类)。我们可以通过操作符@访问接口中的数据。但最好是不直接访问接口的数据,而是定义一些特殊的方法来访问这些数据。

虚类就是不会用来生成实例的类。它们是用来将拥有不同的representations的类链接起来,可以通过虚类为这些不同的representations提供相似的功能。一个标准的做法就是建立一个虚类,然后用其它类来扩展它。在实际中可以通过以下几种不同的方式来使用该虚类。

1.虚类的方法将用到其所有的扩展类中。

2.新类的接口将与虚类的接口的数据类型一致,这样可以使接口的多样化。

3.虚类的接口将会出现在它的所有扩展类中。

下面我们用类来表示一个树状图。一个树状图的结点有三个值:高度、左结点、右结点。终端结点与之不同,有一个高度和一个值(也有可能是另一个对象的实例。)我们可以用一个虚类dendNode来表示该结构。我们可以再定义两个该类的扩展类:终端和非终端结点如图2所示

图2 虚类的表示

这样我们就可以创建树了,它的结点或者是终端结点或者是非终端节点。在类dnode中,它的左节点和右节点都是dendNode类的实例,而dnode类本身又是dendNode的扩展。在此例中虚类被用来允许两个不同的类:左节点和右节点。这种设计使得可以重复使用树变得简单。

在实际的应用中,我们经常会出现这样的问题,希望一个接口或者是一个列表或者是一个空对象(NULL())由于它们不能共享同一个接口。我们可以创建一个虚类来扩展列表类和NULL()类。有两种方法可以建立虚类,(一)与上面一样,用setClass()建立一个没有representation的类;(二)在参数representation中包括类“VIRTUAL”

(三)初始化

对创建的类有两种办法可以用来控制类的实例生成的对象的初始值,用参数prototype来控制值和为该类指定一个initialize方法。这里举其中一个赋值实例如图3所示。

图3 使用initialize赋值

(四)定义方法

方法就是一种特殊的函数,它能根据特定的输入对象执行需要执行的任务。泛型函数的工作就是针对不同的输入参数决定什么样的方法被执行。一旦对泛型函数进行了签名,那么泛型函数就不能添加新的参数了。在设计泛型函数的参数时,要将可能用到的参数都包括进来。比如我们定义一个名为whatIs()的函数,该函数返回对象的类型。>whatis

还可以更复杂一点,比如说打印出对象的长度,定义如下:

>whatis

这样又改进了一步,但是还是有点不尽如人意的地方,这里只给出了函数的长度。对于矩阵,我们更想知道它的行数和列数。所以需要为function类和matrix类单独定义函数,才能得到期望的信息,定义过程如下:

>whatis.fuction

>whatis.matrix

ncol(object),”列\n”)

至此我们定义了三个功能类似的函数,程序变得散乱,使用也变得比较繁琐。希望能通过一个统一的函数名whatIs()来代表上述三个函数,然后根据输入的参数的类型(function,matrix或其它)来决定使用哪一个函数(whatIs.function(),matrix()或whatIs())。使用函数setMethod(),过程如下所示:

>setmethod(“whatis”,”function”,whatis.function)/*用函数whatis建立新的同属函数*/

>setmethod(“whatis”,“matrix”,whatis.matrix)

这样我们只用一个函数whatIs()就可以根据参数的类型执行不同的程序代码。whatIs()我们称之为泛型函数(上面的输出显示为“standardGeneric”),分别针对不同类型的对象的三个不同的程序功能称为方法。setMethod()函数的三个参数分别告诉setMethod对什么泛型函数指定方法,执行该方法对应的参数的类型,执行的方法。其中第二项称为签名(signature)。

三、结束语

要用R编写通用的函数、对象和类,需要重新思考已经习惯的传统过程式编程。需要理解泛型函数和可以用它们编写的“外翻式”OOP,本文的实例证实了使用面向对象编程方法可以有效的简化程序,使编程更有效率,为开发和创建可重用的和模块化的组件提供了一个捷径。

参考文献:

[1]薛毅,陈立萍.统计建模与R软件[M].清华大学出版社,2007,4,1

[2]汤银才.R语言与统计分析[M].高等教育出版社,2006,1,1

[3]XF Wang,YH Xie,JT Li.R for beginners[M],2006,8,1

[4]王斌会.R语言统计分析软件教程[M].中国教育文化出版社,2007,1,1

[5]胡荣兴.R语言的编程方法[J].统计之都,2009,7,14

上一篇:消除含氰废气隐患提高丙烯腈装置安全环保水平 下一篇:数字化校园规划与实践