2012-03-01 83 views
71

面向對象程序設計是R.很可能然而,不同於例如Python中,有很多方法可以實現面向對象:R和麪向對象在這種或那種方式編程

我的問題是:

什麼主要差異區分這些方式的R在OO編程?

理想情況下,這裏的答案將作爲R程序員試圖確定哪種OO編程方法最適合他們的需求的參考。

因此,我要求的是細節,以客觀的方式,根據經驗提出,並以事實和參考爲後盾。說明的獎勵積分如何這些方法映射到標準的OO實踐。

+1

參考資料上的信息:http://stackoverflow.com/questions/5137199/what-is-the-significance-of-the-new-reference-classes – 2012-03-01 18:29:07

+0

謝謝,你能重新發布鏈接作爲答案嗎?如果你可以包含什麼參考類的小概要,以及爲什麼他們更喜歡S3/S4類,那將會很好。 – 2012-03-01 18:34:19

+0

一隻小鳥在我耳邊低聲說約翰錢伯斯即將出版一本書。但不要告訴任何人我說過的話; ;-) – 2012-03-01 18:41:53

回答

32

S3類

  • 不是真的對象,更多的命名約定
  • 周圍爲主。語法:例如打印,print調用print.lmprint.anova等,如果沒有找到,print.default

S4類

參考類

R6類

  • By-reference
  • 不依賴於S4類
  • Creating R6類與引用類相似,不同之處在於不需要分隔字段和方法,也不能指定字段的類型。」在12年3月8日
+1

如果你有其他的不同點,可以隨意編輯。如果它變成CW,我不會哭的:-) – 2012-03-01 19:45:58

+3

別忘了'library(「fortunes」);財富(「海峽」)' – 2012-03-01 21:01:29

+1

關於S4類的討論在這裏:http://stackoverflow.com/questions/3602154/when-does-it-pay-off-to-use-s4-methods-in-r-programming 。總的感覺似乎是,他們在獲得優勢時更麻煩。 – 2012-03-01 22:48:17

19

編輯:答案下面響應一塊它現在已經被刪除了最初發布問題。我已將其複製到下面,爲我的答案提供上下文:

不同的OO方法如何映射到例如在標準方法中使用的更標準的OO方法。 Java還是Python?


我的貢獻涉及到第二個問題,關於R的OO方法是如何映射到更標準的OO方法。正如我以前想過的那樣,我一次又一次地回到了兩段,一段是弗里德里希萊施,另一段是約翰錢伯斯。他們都很好地闡述了爲什麼R中類OO編程與其他許多語言相比具有不同的風格。

首先,弗里德里希Leisch,從「創建R程序包:教程」(warning: PDF):

S是罕見的,因爲它是交互和對面向對象的系統。顯然,設計類是編程,但要使S成爲交互式數據分析環境很有用,它是一種功能語言是合理的。在「真正的」面向對象編程(OOP)語言(如C++或Java類)和方法定義緊密綁定在一起時,方法是類(以及對象)的一部分。我們希望像預定義類的用戶定義方法那樣增加和交互式添加。這些添加可以在任何時間點進行,即使在我們分析數據集時,也可以在命令行提示符下進行。 S試圖在面向對象和交互使用之間做出妥協,雖然折衷在所有他們試圖達到的目標上都不是最優的,但它們在實踐中往往工作得非常出色。

另一段來自約翰錢伯斯的精湛書籍"Software for Data Analysis"。 (Link to quoted passage):

的OOP編程模型在所有S語言,但第一 點不同,即使S和一些其他功能的語言支持類 和方法。 OOP系統中的方法定義是本地的; 沒有要求同一個方法的名稱意味着相同的 事情爲一個不相關的類。相比之下,R中的方法定義並不是 駐留在類定義中;從概念上講,它們與通用 函數相關聯。類定義直接進入確定方法選擇,直接 或通過繼承。使用面向對象編程模型有時 沮喪或困惑,他們的節目不會直接轉移到R, 但它不能。所述功能使用的方法比較複雜,但可以具有有意義的功能也 更切合,並且不能被降低到 OOP版本。

13

S3和S4似乎是面向對象編程的官方(即內置)方法。我已經開始使用S3與嵌入在構造函數/方法中的函數的組合。我的目標是有一個對象$ method()類型的語法,以便我有半私人領域。我說半私密,因爲沒有辦法真正隱藏它們(據我所知)。下面是一個簡單的例子,實際上並沒有做任何事情:

#' Constructor 
EmailClass <- function(name, email) { 
    nc = list(
     name = name, 
     email = email, 
     get = function(x) nc[[x]], 
     set = function(x, value) nc[[x]] <<- value, 
     props = list(), 
     history = list(), 
     getHistory = function() return(nc$history), 
     getNumMessagesSent = function() return(length(nc$history)) 
    ) 
    #Add a few more methods 
    nc$sendMail = function(to) { 
     cat(paste("Sending mail to", to, 'from', nc$email)) 
     h <- nc$history 
     h[[(length(h)+1)]] <- list(to=to, timestamp=Sys.time()) 
     assign('history', h, envir=nc) 
    } 
    nc$addProp = function(name, value) { 
     p <- nc$props 
     p[[name]] <- value 
     assign('props', p, envir=nc) 
    } 
    nc <- list2env(nc) 
    class(nc) <- "EmailClass" 
    return(nc) 
} 

#' Define S3 generic method for the print function. 
print.EmailClass <- function(x) { 
    if(class(x) != "EmailClass") stop(); 
    cat(paste(x$get("name"), "'s email address is ", x$get("email"), sep='')) 
} 

和一些測試代碼:

test <- EmailClass(name="Jason", "[email protected]") 
    test$addProp('hello', 'world') 
    test$props 
    test 
    class(test) 
    str(test) 
    test$get("name") 
    test$get("email") 
    test$set("name", "Heather") 
    test$get("name") 
    test 
    test$sendMail("[email protected]") 
    test$getHistory() 
    test$sendMail("[email protected]") 
    test$getNumMessagesSent() 

    test2 <- EmailClass("Nobody", "[email protected]") 
    test2 
    test2$props 
    test2$getHistory() 
    test2$sendMail('[email protected]') 

這裏是一個博客帖子我寫的這個做法的鏈接:http://bryer.org/2012/object-oriented-programming-in-r我歡迎評論,批評和建議,因爲如果這是最好的方法,我不相信自己。但是,對於我試圖解決的問題,它效果很好。特別是,對於makeR軟件包(http://jbryer.github.com/makeR),我不希望用戶直接更改數據字段,因爲我需要確保表示對象狀態的XML文件保持同步。只要用戶遵守我在文檔中概述的規則,就可以很好地工作。

+10

你有點用上面的代碼「手動」重新創建參考類...它只是讓事情變得更加脆弱。 – 2012-03-07 19:09:54

+0

謝謝西蒙。直到我發佈這個消息之後,我才意識到ReferenceClasses。 – jbryer 2012-03-09 13:56:32