R语言泛型函数及S3,S4对象机制

 


泛型函数:
一组不同的函数定义同一个通用名称,关联不同对象,处理不同对象表现不同行为.(R的函数重载机制),R中S3对象的方法和S4类的方法是通过泛型函数机制关联到目标,方法通过S3和S4泛型函数机制绑定到S3对象和S4类上的.

S3对象:是基于泛型函数的面向对象机制.S3对象可看作是一个list并有一个名为class的属性.S3没有正式的类型定义.
> t<-structure(1,class="foo") #返回一个S3类
> t
[1] 1
attr(,"class")
[1] "foo"

> p=list(a=1,b=2) #生成列表,为对象class属性赋值.构造S3对象.
> class(p)="foo"
> p
$a
[1] 1
$b
[1] 2
attr(,"class")
[1] "foo"

S3泛型函数:基于泛型的面向对象,通过S3泛型函数分派.
> bar<-function(o) UseMethod("bar")#bar函数调用UseMethod("bar"),UseMethod依据o的类,search对应的bar.*方法,没有找到如果存在bar.default则调用,否则报错.
> bar.default<-function(o) "default"     
> bar.foo<-function(o) "foo"               
> bar(t)      #调用了bar.foo
[1] "foo"
> bar(123)    #调用了bar.default
[1] "default"
> bar(p)
[1] "foo"
> bar<-function(o=123) UseMethod("bar",o)#指定bar默认对象
> bar() #默认使用了bar(123)
[1] "default"
> bar<-function(o=t) UseMethod("bar",o)
> bar()#默认使用了bar(t)
[1] "foo"
S3面向对象机制,是一系列命名规则构造的,generic.class命名方式决定了其行为.分派过程是一种按照命名规则搜索对应函数的过程.
查找隐藏S3方法,可以得到隐藏在泛型方法后面的普通方法即信息
> getAnywhere(bar.foo)
>  getAnywhere(bar.foo)
A single object matching ‘bar.foo’ was found
It was found in the following places
  .GlobalEnv
  registered S3 method for bar
with value
function(o) "foo"
> f=getS3method(f="bar",class="foo")
> f
function(o) "foo"
> f(1)
[1] "foo"
构建一个S4类foo,new(foo),S3泛型函数bar调用了bar.foo,S3泛型函数只是基于命名规则的查找,任何class属性为"foo"的对象都会由UseMethod查找到bar.foo.
> setClass("foo",representation = (data="numeric"))
> l=new("foo")
> l
An object of class "foo"
numeric(0)
> class(l)
[1] "foo"
attr(,"package")
[1] ".GlobalEnv"
> bar(l) #bar.foo
[1] "foo"

S4泛型函数:S4使用S4泛型函数机制分派方法,S4泛型不是基于命名固定规则查找。而是通过注册将某个对象及其对应处理的方法关联起来.
将普通函数注册为泛型函数,原普通函数可以被重载。原普通函数是泛型函数的基本框架,当处理对象的类别没有重载的方法,则使用的是原普通函数,有重载则调用重载函数.

> series<-function(o){"series"} #定义一个普通函数
> setGeneric("series") #注册为泛型函数
> series
standardGeneric for "series" defined from package ".GlobalEnv"
function (o) 
standardGeneric("series")
<environment: 0x4fc9388>
Methods may be defined for arguments: o
Use  showMethods("series")  for currently available ones.
> showMethods(series)
Function: series (package .GlobalEnv)
o="ANY"
> series()
"series"
> series(123)
[1] "series"
> series(p) #p is S3对象 class(p) is foo
[1] "series"
#对象没有指定函数,默认使用了series自身,并将类型信息写在了广义函数中
> showMethods(series)
Function: series (package .GlobalEnv)
o="ANY"
o="foo"
    (inherited from: o="ANY")
o="missing"
    (inherited from: o="ANY")
o="numeric"
    (inherited from: o="ANY")
    
#设置了foof,food类型,及其自定义的关联函数.自己设置的没有(inherited from: o="ANY")
> setMethod(series,signature = c("foof"),definition = function(o){"foof"})
> setMethod(series,signature = c("food"),definition = function(o){"food"})
> showMethods(series)
Function: series (package .GlobalEnv)
o="ANY"
o="food"
o="foof"
#定义两个S3对象,设置为food类,和foof类
> a=1
> class(a)="food"
> b=1
> class(b)="foof"
#S4泛型series依据传入对象的class属性,在自己的方法设置列表中寻找对应类别以及对应的函数对象,执行重载函数。
#S4泛型也是基于class属性查找对应函数.
> series(a)
[1] "food"
> series(b)
[1] "foof"
#def参数在注册广义函数时,同时定义函数原型==先定义原型+后注册泛型函数
> setGeneric("pq",def=function(o){"pq"})
[1] "pq"
> pq
standardGeneric for "pq" defined from package ".GlobalEnv"
function (o) 
standardGeneric("pq")
<environment: 0x5118ac8>
Methods may be defined for arguments: o
Use  showMethods("pq")  for currently available ones.
> pq()
[1] "pq"


S4对象:实现了oop机制。有基本的类型,继承,封装等。S4对象从基本类new构造,有基本的类型。S4对象的方法不同于C++等语言,定义类的方法。而是通过泛型范数机制。定义一个泛型函数,然后设置特定类及其特定方法。将泛型范数关联到对象。方法绑定对象,不是C++等语言的对象.方法。因此R中"."不是运算符,是一个普通字符,可以出现在符号(变量名)中。data.frame()表示名为"data.frame"的函数而不是data对象的frame函数.

> setClass("l",representation(data="numeric"))
> setClass("fp",representation(d="numeric"),contains = c("l")) #contains指定继承
> f=new("fp") #new对象,未赋初值
> f
> f@d=1
> f@data=2
> f
An object of class "fp"
Slot "d":  
[1] 1
Slot "data": #继承自l
[1] 2
#设置类的initialize泛型函数,initialize相当于构造函数.
> setMethod(initialize,signature = c("fp"),definition = function(.Object){print("hello");.Object})
[1] "initialize"
attr(,"package")
[1] "methods"
> ff=new("fp")
[1] "hello"
为一批类指定某个方法时,可以为这批类指定一个虚类为父类.然后为虚父类,写一个方法.(类比java接口)
> setClass("a",representation(data="numeric"))
> setClass("b",representation(data="numeric"))
> setClassUnion("vb",c("a","b")) #指定a,b虚父类为vb
> new("vb")
Error in new("vb"):无法从虚拟类别("vb")中产生对象 #虚类无法new
> setMethod(series,signature = c("vb"),function(o){"virtual base"}) #为vb指定方法
> showMethods(series)
Function: series (package .GlobalEnv)
o="ANY"
o="food"
o="foof"
o="vb"
> a1=new("a")
> b1=new("b")
> series(a1)       #调用了vb的方法.
[1] "virtual base"
> series(b1)
[1] "virtual base"
> setMethod(series,signature = c("a"),function(o){"a"}) #重写a的series方法
> showMethods(series)
Function: series (package .GlobalEnv)
o="a"
o="ANY"
o="food"
o="foof"
o="vb"
> series(a1) #此时调用了a的series方法,覆盖了虚父类的方法
[1] "a"
> series(b1)
[1] "virtual base"
> showMethods(series)
Function: series (package .GlobalEnv)
o="a"
o="ANY"
o="b"
    (inherited from: o="vb") #继承自vb
o="food"
o="foof"

 

o="vb"

 

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值