R和面向对象的编程


80

在R中,以一种或另一种方式进行面向对象的编程非常有可能。但是,与例如Python不同,有许多方法可以实现面向对象:

我的问题是:

有哪些主要区别区分R中的OO编程这些方式?

理想情况下,此处的答案将为试图确定哪种OO编程方法最适合其需求的R程序员提供参考。

因此,我要求提供详细信息,以经验为基础,以客观的方式提出,并以事实和参考为后盾。阐明这些方法如何映射到标准OO做法的要点。



谢谢,您可以将链接重新发布为答案吗?如果您可以包括什么是参考类,以及为什么它们相对于S3 / S4类更可取,则将是一个很好的总结。
Paul Hiemstra'3

一只小鸟在我耳边窃窃私语,约翰·钱伯斯(John Chambers)即将出版一本关于这本书的书。但请不要告诉我我说的那
件事

1
同样的小鸟儿能否在下面贴上答案,并提供有关防御课的更多信息;)
Paul Hiemstra'3

Answers:


34

S3班

  • 不是真正的对象,更多是命名约定
  • 基于。语法:例如用于打印,print通话print.lm print.anova等。如果找不到,print.default

S4班

参考班

原型

  • ggplot2最初是用原型编写的,但最终将使用S3进行重写。
  • 简洁的概念(原型,而不是类),但在实践中似乎很棘手
  • ggplot2的下一版本似乎正在远离它
  • 概念和实现的描述

R6班

  • 引用
  • 不依赖于S4类
  • 创建R6类与引用类相似,不同之处在于,无需分隔字段和方法,并且您无法指定字段的类型。”

1
如果您要添加其他差异,请随时进行编辑。如果它变成CW,我就不会哭了:-)
Ari B. Friedman 2012年

3
不要忘记library("fortunes"); fortune("strait")
Ben Bolker 2012年

1
此处有关S4类的讨论:stackoverflow.com/questions/3602154/…。总体感觉似乎是,他们麻烦多了才有优势。
Paul Hiemstra'3

有趣的是,新的R6类通过避免使用该数字来隐式承认引用类是R5。让争议开始(重新)。
Ari B. Friedman

1
R5名称最初是由引用类的开发人员以外的其他人所戏称的。名称R6是对“ R5”的认可,但这并不意味着R5名称具有任何正式认可。
2014年

19

编辑于2012年3月8日:以下答案回答了最初发布的问题,此问题已被删除。我在下面复制了它,以提供答案的上下文:

不同的OO方法如何映射到Java或Python中使用的更标准的OO方法?


我的贡献与您的第二个问题有关,即R的OO方法如何映射到更标准的OO方法。过去我一直在想这件事,我一次又一次地回到两篇文章中,一篇是弗里德里希·莱施(Friedrich Leisch)撰写的,另一篇是约翰·钱伯斯(John Chambers)撰写的。两者都很好地阐明了为什么R中类似于OO的编程与许多其他语言相比具有不同的风格。

首先,Friedrich Leisch,摘自“创建R包:教程”(警告:PDF):

S很少见,因为它既是交互式的又具有面向对象的系统。设计类显然是编程,但要使S作为交互式数据分析环境有用,就可以认为S是一种功能语言。在像C ++或Java这样的“真正的”面向对象编程(OOP)语言中,类和方法定义紧密地绑定在一起,方法是类的一部分(因此是对象)。我们想要增量式和交互式添加,例如用于预定义类的用户定义方法。这些添加可以在任何时间点进行,甚至在我们分析数据集时在命令行提示符下即时进行。S试图在面向对象和交互使用之间做出折衷,尽管折衷对于他们尝试达成的所有目标从来都不是最佳选择,但在实践中它们通常表现出令人惊讶的出色表现。

另一段来自约翰·钱伯斯(John Chambers)的绝妙著作“数据分析软件”。(链接至引用的段落):

OOP编程模型除第一点外,在所有方面都与S语言不同,即使S和其他一些功能语言也支持类和方法。OOP系统中的方法定义在该类中是本地的。不需要方法的相同名称对于不相关的类意味着相同的事物。相比之下,R中的方法定义不驻留在类定义中。从概念上讲,它们与通用功能相关联。类定义直接或通过继承输入来确定方法选择。习惯于OOP模型的程序员有时会感到沮丧或困惑,因为他们的编程没有直接转移到R,但不能转移到R。方法的功能使用更加复杂,但也更加具有有意义的功能,因此不能简化为OOP版本。


14

S3和S4似乎是OO编程的正式(即内置)方法。我已经开始使用S3与构造函数/方法中嵌入的函数的组合。我的目标是拥有一个object $ 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", "jason@bryer.org")
    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("jbryer@excelsior.edu")
    test$getHistory()
    test$sendMail("test@domain.edu")
    test$getNumMessagesSent()

    test2 <- EmailClass("Nobody", "dontemailme@nowhere.com")
    test2
    test2$props
    test2$getHistory()
    test2$sendMail('nobody@exclesior.edu')

这是我写的有关此方法的博客文章的链接:http : //bryer.org/2012/object-directional-programming-in-r不赞成对此方法发表评论,提出批评和建议,我对此表示欢迎。我自己,如果这是最好的方法。但是,对于我试图解决的问题,它的效果很好。具体来说,对于makeR包(http://jbryer.github.com/makeR),我不希望用户直接更改数据字段,因为我需要确保代表我对象状态的XML文件保持同步。只要用户遵守我在文档中概述的规则,此方法就可以完美工作。


10
您有点用上面的代码“手工”重新创建了引用类……这使事情变得更加脆弱。
Simon Urbanek'3

谢谢西蒙。在发布此内容之前,我还没有意识到ReferenceClasses。
jbryer 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.