S4Class
泛型函數(shù)
#需要新的方式表示數(shù)據(jù)腾节,或者需要新函數(shù)根據(jù)不同參數(shù)類型做出不同反應(yīng)
#R的OOP是基于泛型函數(shù)的
#創(chuàng)建泛型函數(shù)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()函數(shù)查看對(duì)象所屬的類,每個(gè)對(duì)象都屬于0或1或多個(gè)類
#使用attr()函數(shù)給a指定類屬性忘嫉,attr(x,"dim")維度屬性
a <- 1:10
attr(a,"class") <- "foo"
#a就相當(dāng)于foo類的一個(gè)對(duì)象
whoAmI(a)
b <- 2:10
attr(b,"class") <- c("baz","bam","bar")
whoAmI(b)
#使用methods()函數(shù)來找到給定泛型函數(shù)的所有實(shí)現(xiàn)方法
methods(whoAmI)
#若實(shí)例屬于多個(gè)在泛型函數(shù)中定義的類,按第一個(gè)類處理
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)
#泛型函數(shù)將不同的方法聚集到一起案腺,
#由R根據(jù)函數(shù)的對(duì)象類型來決定選擇執(zhí)行那個(gè)方法```
#類
setClass(Class,representation(),prototype = ,contains = )
Class為字符串庆冕,表示類的名稱
representation為建立成員變量與其明確的類型
numeric,character,logical
prototype為接口提供默認(rèn)的數(shù)據(jù)對(duì)象
contains該類所擴(kuò)展的類,所有擴(kuò)展的類的新實(shí)例都會(huì)繼承其所有父類的接口
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()為此類創(chuàng)建一個(gè)實(shí)例,第一個(gè)參數(shù)是類的字符串
x <- new("baz",a="xxx",b=5,c=3,d=9)
使用@操作符訪問成員變量救湖,寫入或者讀取
x@a <- "xyz"
或者使用slot()函數(shù)
slot(x,"a") <- "i love you"```
虛類
#虛類是不會(huì)用來生成實(shí)例的類
#它們用來將擁有不同的representation的類(它們不能互相繼承,如foo和bar)
#連接起來愧杯,通過虛類為這些不同的representation提供相似的功能
#建立一個(gè)虛類,用其他類來擴(kuò)展它
#一個(gè)樹狀圖的表示
setClass("dendNode")
setClass("dnode",representation(left="dendNode",right="dendNode",
height="numeric"),contains = "dendNode")
setClass("tnode",representation(height="numeric",value="numeric",
label="character"),contains = "dendNode")```
#初始化和原型
控制類的實(shí)例生成對(duì)象的成員變量的初始值
setClass("xx",representation(a="numeric",b="character"),
prototype(a=3,b="hi there"))
new("xx")
或者是給該類指定一個(gè)Initialize方法鞋既,用該方法為類的實(shí)例賦值
帶‘initialize’標(biāo)記方法傳入?yún)?shù)為.Object
并且在initialize方法中返回該對(duì)象
setMethod("initialize","xx",function(.Object,b)
{
.Object@b <- b
.Object@a <- nchar(b)
.Object
})
new("xx",b="yowser")```
泛型函數(shù)與方法
#泛型函數(shù)實(shí)際上是一個(gè)分派機(jī)制,根據(jù)不同的輸入?yún)?shù)決定什么樣的方法被執(zhí)行
#方法是特殊的函數(shù)耍铜,根據(jù)特定的輸入對(duì)象執(zhí)行需要執(zhí)行的任務(wù)
whatIs <- function(object) data.class(object)
whatIs(1:10)
whatIs1 <- function(object) cat("類:",data.class(object),"\n長度:",
length(object),"\n")
whatIs1(1:10)
#對(duì)于函數(shù)與矩陣單獨(dú)建立處理函數(shù)
whatIs1.function <- function(object){
cat("類:",data.class(object),"\n")
}
#如果whatIs1函數(shù)定義為UseMethod()就可以真正的形成不用指定類的泛型函數(shù)
whatIs1.function(whatIs)
whatIs1.matrix <- function(object){
cat("類:",data.class(object),"\n",nrow(object),"行",ncol(object),"列\(zhòng)n")
}
A <- matrix(1:6,nrow=3)
whatIs1.matrix(A)```
#定義方法
使用統(tǒng)一的函數(shù)名來處理邑闺,根據(jù)輸入?yún)?shù)的類型決定使用哪個(gè)函數(shù)
S4類中使用setMethod()
第一個(gè)參數(shù)設(shè)定定義給定類的泛型函數(shù)名
第二個(gè)參數(shù)是類的名稱,稱為簽名,第三個(gè)就是要處理的函數(shù)
setMethod("whatIs","function",whatIs.function)
setMethod("whatIs","matrix",whatIs1.matrix)
告訴setMethod對(duì)什么泛型函數(shù)指定方法棕兼,執(zhí)行該方法對(duì)應(yīng)的參數(shù)類型陡舅,執(zhí)行的方法
whatIs(A)
whatIs(whatIs)```
訪問子函數(shù)
#@來訪問接口,實(shí)際中使用子函數(shù)訪問接口伴挚,成員變量
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")#泛型函數(shù)
#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)
}
#定義一個(gè)泛型函數(shù)的給定類的方法
setMethod("a","foo",function(object) object@abc)
b <- new("foo",abc=10)
a(b)```