S4Class
泛型函数
#需要新的方式表示数据,或者需要新函数根据不同参数类型做出不同反应
#R的OOP是基于泛型函数的
#创建泛型函数UseMethod()
whoAmI <- function(x,...) UseMethod("whoAmI")
whoAmI.foo <- function(x) print("I am a foo")
whoAmI.bar <- function(x) print("I am a bar")
whoAmI.default <- function(x) print("I don't know who I am")
#用class()函数查看对象所属的类,每个对象都属于0或1或多个类
#使用attr()函数给a指定类属性,attr(x,"dim")维度属性
a <- 1:10
attr(a,"class") <- "foo"
#a就相当于foo类的一个对象
whoAmI(a)
b <- 2:10
attr(b,"class") <- c("baz","bam","bar")
whoAmI(b)
#使用methods()函数来找到给定泛型函数的所有实现方法
methods(whoAmI)
#若实例属于多个在泛型函数中定义的类,按第一个类处理
meth1 <- function(x) UseMethod("meth1")
meth1.Mom <- function(x) print("Mom's meth1")
meth1.Dad <- function(x) print("Dad's meth1")
meth2 <- function(x) UseMethod("meth2")
meth2.Dad <- function(x) print("Dad's meth2")
a <- 1:10
attr(a,"class") <- c("Mom","Dad")
meth1(a)
meth2(a)
#泛型函数将不同的方法聚集到一起,
#由R根据函数的对象类型来决定选择执行那个方法```
#类
setClass(Class,representation(),prototype = ,contains = )
Class为字符串,表示类的名称
representation为建立成员变量与其明确的类型
numeric,character,logical
prototype为接口提供默认的数据对象
contains该类所扩展的类,所有扩展的类的新实例都会继承其所有父类的接口
setClass("foo",representation(a="character",b="numeric"))
setClass("bar",representation(c="numeric",d="numeric"))
继承foo和bar类
setClass("baz",contains = c("foo","bar"))
getClass("baz")
使用new()为此类创建一个实例,第一个参数是类的字符串
x <- new("baz",a="xxx",b=5,c=3,d=9)
使用@操作符访问成员变量,写入或者读取
x@a <- "xyz"
或者使用slot()函数
slot(x,"a") <- "i love you"```
虚类
#虚类是不会用来生成实例的类
#它们用来将拥有不同的representation的类(它们不能互相继承,如foo和bar)
#连接起来,通过虚类为这些不同的representation提供相似的功能
#建立一个虚类,用其他类来扩展它
#一个树状图的表示
setClass("dendNode")
setClass("dnode",representation(left="dendNode",right="dendNode",
height="numeric"),contains = "dendNode")
setClass("tnode",representation(height="numeric",value="numeric",
label="character"),contains = "dendNode")```
#初始化和原型
控制类的实例生成对象的成员变量的初始值
setClass("xx",representation(a="numeric",b="character"),
prototype(a=3,b="hi there"))
new("xx")
或者是给该类指定一个Initialize方法,用该方法为类的实例赋值
带‘initialize’标记方法传入参数为.Object
并且在initialize方法中返回该对象
setMethod("initialize","xx",function(.Object,b)
{
.Object@b <- b
.Object@a <- nchar(b)
.Object
})
new("xx",b="yowser")```
泛型函数与方法
#泛型函数实际上是一个分派机制,根据不同的输入参数决定什么样的方法被执行
#方法是特殊的函数,根据特定的输入对象执行需要执行的任务
whatIs <- function(object) data.class(object)
whatIs(1:10)
whatIs1 <- function(object) cat("类:",data.class(object),"\n长度:",
length(object),"\n")
whatIs1(1:10)
#对于函数与矩阵单独建立处理函数
whatIs1.function <- function(object){
cat("类:",data.class(object),"\n")
}
#如果whatIs1函数定义为UseMethod()就可以真正的形成不用指定类的泛型函数
whatIs1.function(whatIs)
whatIs1.matrix <- function(object){
cat("类:",data.class(object),"\n",nrow(object),"行",ncol(object),"列\n")
}
A <- matrix(1:6,nrow=3)
whatIs1.matrix(A)```
#定义方法
使用统一的函数名来处理,根据输入参数的类型决定使用哪个函数
S4类中使用setMethod()
第一个参数设定定义给定类的泛型函数名
第二个参数是类的名称,称为签名,第三个就是要处理的函数
setMethod("whatIs","function",whatIs.function)
setMethod("whatIs","matrix",whatIs1.matrix)
告诉setMethod对什么泛型函数指定方法,执行该方法对应的参数类型,执行的方法
whatIs(A)
whatIs(whatIs)```
访问子函数
#@来访问接口,实际中使用子函数访问接口,成员变量
setClass("foo",representation(abc="ANY"))
#is there a function named a,and if so,is it a generic(类)?
if(!isGeneric("a")){
if(is.function("a")) fun <- a
#dispatches a method from the current function call for the generic function a
else fun <- function(object) standardGeneric("a")#泛型函数
#if there is already a non-generic function of this name
#it will be used to define the generic,and the current function will
#become the default method for the generic
setGeneric("a",fun)
}
#定义一个泛型函数的给定类的方法
setMethod("a","foo",function(object) object@abc)
b <- new("foo",abc=10)
a(b)```