R开发(part10)--基于S3的面向对象编程
學(xué)習(xí)筆記,僅供參考,有錯必糾
參考自:《R的極客理想》-- 張丹
文章目錄
- R開發(fā)
- 面向?qū)ο?/li>
- 面向?qū)ο蟮腞語言實現(xiàn)
- 基于S3的面向?qū)ο缶幊?/li>
- 泛型函數(shù)和方法調(diào)用
- 查看S3對象的函數(shù)
- S3對象的繼承調(diào)用方式
- S3對象的缺點
R開發(fā)
面向?qū)ο?/h3>
R語言中有三種面向?qū)ο蟮木幊虒崿F(xiàn),即S3類型、S4類型和RC類型。S3和S4都是基于泛型函數(shù)的,RC則是完全的面向?qū)ο髮崿F(xiàn)。
面向?qū)ο蟮腞語言實現(xiàn)
定義老師對象和行為,封裝到teacher()泛型函數(shù)中;
定義同學(xué)對象和行為,封裝到student()泛型函數(shù)中.
#定義老師對象和行為 teacher <- function(x, ...) UseMethod("teacher") teacher.lecture <- function(x) print("講課") teacher.assignment <- function(x) print("布置作業(yè)") teacher.correcting <- function(x) print("批改作業(yè)") teacher.default<-function(x) print("你不是teacher")#定義同學(xué)對象和行為 student <- function(x, ...) UseMethod("student") student.attend <- function(x) print("聽課") student.homework <- function(x) print("寫作業(yè)") student.exam <- function(x) print("考試") student.default<-function(x) print("你不是student")#定義變量a和b a <- "teacher" b <- "student"attr(a, "class") <- "lecture" attr(b, "class") <- "attend"teacher(a) #"講課" student(b) #"聽課"#把老師和同學(xué)的行為都賦予到一個變量ab上 ab <- "teacher_student" #分別設(shè)置不同對象的行為 attr(ab, "class") <- c("assignment", "homework")#執(zhí)行老師的行為 teacher(ab) #"布置作業(yè)" #執(zhí)行同學(xué)的行為 student(ab) #"寫作業(yè)"基于S3的面向?qū)ο缶幊?/h4>
在R語言中,基于S3對象的面向?qū)ο缶幊?#xff0c;是一種基于泛型函數(shù)的實現(xiàn)方式。泛型函數(shù)是一種特殊的函數(shù),根據(jù)傳入對象的類型決定調(diào)用哪個具體的方法。基于S3對象實現(xiàn)的面向?qū)ο缶幊?#xff0c;不同于其他語言的面向?qū)ο缶幊?#xff0c;是一種動態(tài)函數(shù)調(diào)用的模擬實現(xiàn)。。S3對象被廣泛應(yīng)用于R的早期的開發(fā)包中。
- 通過變量創(chuàng)建S3對象
創(chuàng)建S3對象最簡單的方法就是給一個變量增加class屬性:
x <- 1 #定義為S3類型對象 attr(x, "class") <- "foo" x #輸出start [1] 1 attr(,"class") [1] "foo" #輸出end otype(x) #"S3"也可以通過structure函數(shù)創(chuàng)建S3對象:
#創(chuàng)建S3類型對象 y <- structure(10, class = "foo") y #輸出start [1] 10 attr(,"class") [1] "foo" #輸出end otype(y) #"S3"- 創(chuàng)建多類型的S3對象
S3對象沒有明確的結(jié)構(gòu)關(guān)系,一個S3對象可以有多個類型。S3對象類型,通過變量的class屬性來定義,class屬性可以是一個向量,所以允許多類型:
z <- 5 attr(z, "class") <- c("foo", "bar") class(z) #"foo" "bar" otype(z) #"S3"泛型函數(shù)和方法調(diào)用
對于S3對象的使用,通常用UseMethod函數(shù)來定義一個泛型函數(shù)的名稱,通過傳入?yún)?shù)的class屬性來確定不同的方法調(diào)用:
#用UseMethod定義teacher泛型函數(shù) teacher <- function(x, ...) UseMethod("teacher") #函數(shù)檢查teacher的類型 ftype(teach) #用teacher.xxx的語法格式定義teacher對象的行為 teacher.lecture <- function(x) print("講課") teacher.correcting <- function(x) print("批改作業(yè)")#teacher.default定義默認(rèn)行為 teacher.default<-function(x) print("teacher默認(rèn)行為")方法調(diào)用時,通過傳入?yún)?shù)的class屬性來確定不同的方法調(diào)用,比如,我們定義一個變量a,并設(shè)置a的class屬性為lecture,將變量a傳入teacher泛型函數(shù)中,teacher.lecture函數(shù)就會被調(diào)用:
a <- "teacherA" attr(a, "class") <- "lecture" #執(zhí)行老師的行為 teacher(a)當(dāng)然,我們也可以直接調(diào)用teacher中定義的行為,如果這樣做就失去了面向?qū)ο蠓庋b的意義:
teacher.lecture() #"講課" teacher.lecture(a) #"講課" teacher() #"teacher默認(rèn)行為"對比其他語言,這里R的泛型函數(shù)就表示方法接口,teacher.xxx表示接口的方法實現(xiàn)。
查看S3對象的函數(shù)
當(dāng)我們使用S3對象進行面向?qū)ο蠓庋b后,可以用methods函數(shù)來查看S3對象中定義的內(nèi)部行為函數(shù):
#查看teacher對象 teacher #輸出start function(x, ...) UseMethod("teacher") <bytecode: 0x0000000015cbe690> #輸出end #查看teacher對象的內(nèi)部函數(shù) methods(teacher) #輸出start teacher.assignment teacher.correcting teacher.default teacher.lecture #輸出end用getAnywhere函數(shù)查看函數(shù):
#查看teacher.lecture getAnywhere(teacher.lecture) #輸出start A single object matching ‘teacher.lecture’ was found It was found in the following places.GlobalEnvregistered S3 method for teacher with valuefunction(x) print("講課") <bytecode: 0x0000000015c48b40> #輸出end #查看不可見的函數(shù)predict.ppr getAnywhere(predict.ppr) #輸出略使用getS3method函數(shù)查看不可見的函數(shù):
getS3method("predict", "ppr") #輸出略S3對象的繼承調(diào)用方式
S3對象可以用NextMethod函數(shù)來實現(xiàn)繼承調(diào)用:
node <- function(x) UseMethod("node", x) node.default <- function(x) print("默認(rèn)node") node.father <- function(x) c("father") #father函數(shù) node.son <- function(x) c("son", NextMethod()) #son函數(shù)n1 <- structure(1, class = c("father")) n2 <- structure(2, class = c("son", "father")) node(n1) #"father" node(n2) #"son" "father"通過對node函數(shù)傳入n2的參數(shù),node.son先被執(zhí)行,然后通過NextMethod函數(shù)繼續(xù)執(zhí)行node.father函數(shù)。其實這樣就模擬了子函數(shù)調(diào)用父函數(shù)的過程,實現(xiàn)面向?qū)ο缶幊讨械睦^承。
S3對象的缺點
-
S3對象并不是完全的面向?qū)ο髮崿F(xiàn),而是一種通過函數(shù)調(diào)用來模擬面向?qū)ο髮崿F(xiàn).
-
S3使用起來簡單,但在實際的面向?qū)ο缶幊踢^程中,當(dāng)對象關(guān)系有一定的復(fù)雜度時,S3對象所表達的意義就會變得不太清楚.
-
S3封裝的內(nèi)部函數(shù)可繞過泛型函數(shù)的檢查直接被調(diào)用.
-
S3參數(shù)的class屬性可以被任意設(shè)置,沒有預(yù)處理的檢查.
-
S3參數(shù)只能通過調(diào)用class屬性進行函數(shù)調(diào)用,其他屬性則不會被class函數(shù)執(zhí)行.
-
S3參數(shù)的class屬性有多個值時,調(diào)用時會按照程序賦值順序來調(diào)用第一個合法的函數(shù).
總結(jié)
以上是生活随笔為你收集整理的R开发(part10)--基于S3的面向对象编程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: R开发(part9)--文件系统管理
- 下一篇: 计算机指令由两部分组成,它们是什么