R开发(part10)--基于S3的面向对象编程
學習筆記,僅供參考,有錯必糾
參考自:《R的極客理想》-- 張丹
文章目錄
- R開發
- 面向對象
- 面向對象的R語言實現
- 基于S3的面向對象編程
- 泛型函數和方法調用
- 查看S3對象的函數
- S3對象的繼承調用方式
- S3對象的缺點
R開發
面向對象
R語言中有三種面向對象的編程實現,即S3類型、S4類型和RC類型。S3和S4都是基于泛型函數的,RC則是完全的面向對象實現。
面向對象的R語言實現
定義老師對象和行為,封裝到teacher()泛型函數中;
定義同學對象和行為,封裝到student()泛型函數中.
#定義老師對象和行為 teacher <- function(x, ...) UseMethod("teacher") teacher.lecture <- function(x) print("講課") teacher.assignment <- function(x) print("布置作業") teacher.correcting <- function(x) print("批改作業") teacher.default<-function(x) print("你不是teacher")#定義同學對象和行為 student <- function(x, ...) UseMethod("student") student.attend <- function(x) print("聽課") student.homework <- function(x) print("寫作業") 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) #"聽課"#把老師和同學的行為都賦予到一個變量ab上 ab <- "teacher_student" #分別設置不同對象的行為 attr(ab, "class") <- c("assignment", "homework")#執行老師的行為 teacher(ab) #"布置作業" #執行同學的行為 student(ab) #"寫作業"基于S3的面向對象編程
在R語言中,基于S3對象的面向對象編程,是一種基于泛型函數的實現方式。泛型函數是一種特殊的函數,根據傳入對象的類型決定調用哪個具體的方法。基于S3對象實現的面向對象編程,不同于其他語言的面向對象編程,是一種動態函數調用的模擬實現。。S3對象被廣泛應用于R的早期的開發包中。
- 通過變量創建S3對象
創建S3對象最簡單的方法就是給一個變量增加class屬性:
x <- 1 #定義為S3類型對象 attr(x, "class") <- "foo" x #輸出start [1] 1 attr(,"class") [1] "foo" #輸出end otype(x) #"S3"也可以通過structure函數創建S3對象:
#創建S3類型對象 y <- structure(10, class = "foo") y #輸出start [1] 10 attr(,"class") [1] "foo" #輸出end otype(y) #"S3"- 創建多類型的S3對象
S3對象沒有明確的結構關系,一個S3對象可以有多個類型。S3對象類型,通過變量的class屬性來定義,class屬性可以是一個向量,所以允許多類型:
z <- 5 attr(z, "class") <- c("foo", "bar") class(z) #"foo" "bar" otype(z) #"S3"泛型函數和方法調用
對于S3對象的使用,通常用UseMethod函數來定義一個泛型函數的名稱,通過傳入參數的class屬性來確定不同的方法調用:
#用UseMethod定義teacher泛型函數 teacher <- function(x, ...) UseMethod("teacher") #函數檢查teacher的類型 ftype(teach) #用teacher.xxx的語法格式定義teacher對象的行為 teacher.lecture <- function(x) print("講課") teacher.correcting <- function(x) print("批改作業")#teacher.default定義默認行為 teacher.default<-function(x) print("teacher默認行為")方法調用時,通過傳入參數的class屬性來確定不同的方法調用,比如,我們定義一個變量a,并設置a的class屬性為lecture,將變量a傳入teacher泛型函數中,teacher.lecture函數就會被調用:
a <- "teacherA" attr(a, "class") <- "lecture" #執行老師的行為 teacher(a)當然,我們也可以直接調用teacher中定義的行為,如果這樣做就失去了面向對象封裝的意義:
teacher.lecture() #"講課" teacher.lecture(a) #"講課" teacher() #"teacher默認行為"對比其他語言,這里R的泛型函數就表示方法接口,teacher.xxx表示接口的方法實現。
查看S3對象的函數
當我們使用S3對象進行面向對象封裝后,可以用methods函數來查看S3對象中定義的內部行為函數:
#查看teacher對象 teacher #輸出start function(x, ...) UseMethod("teacher") <bytecode: 0x0000000015cbe690> #輸出end #查看teacher對象的內部函數 methods(teacher) #輸出start teacher.assignment teacher.correcting teacher.default teacher.lecture #輸出end用getAnywhere函數查看函數:
#查看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 #查看不可見的函數predict.ppr getAnywhere(predict.ppr) #輸出略使用getS3method函數查看不可見的函數:
getS3method("predict", "ppr") #輸出略S3對象的繼承調用方式
S3對象可以用NextMethod函數來實現繼承調用:
node <- function(x) UseMethod("node", x) node.default <- function(x) print("默認node") node.father <- function(x) c("father") #father函數 node.son <- function(x) c("son", NextMethod()) #son函數n1 <- structure(1, class = c("father")) n2 <- structure(2, class = c("son", "father")) node(n1) #"father" node(n2) #"son" "father"通過對node函數傳入n2的參數,node.son先被執行,然后通過NextMethod函數繼續執行node.father函數。其實這樣就模擬了子函數調用父函數的過程,實現面向對象編程中的繼承。
S3對象的缺點
-
S3對象并不是完全的面向對象實現,而是一種通過函數調用來模擬面向對象實現.
-
S3使用起來簡單,但在實際的面向對象編程過程中,當對象關系有一定的復雜度時,S3對象所表達的意義就會變得不太清楚.
-
S3封裝的內部函數可繞過泛型函數的檢查直接被調用.
-
S3參數的class屬性可以被任意設置,沒有預處理的檢查.
-
S3參數只能通過調用class屬性進行函數調用,其他屬性則不會被class函數執行.
-
S3參數的class屬性有多個值時,調用時會按照程序賦值順序來調用第一個合法的函數.
總結
以上是生活随笔為你收集整理的R开发(part10)--基于S3的面向对象编程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: R开发(part9)--文件系统管理
- 下一篇: R开发(part11)--基于S4的面向