"S3方法"在R中意味着什么?

jig*_*soo 115 oop r r-s3 r-s4 r-faq

由于我是R的新手,我不知道S3方法和对象是什么.我发现有S3和S4对象系统,如果可能的话,有些人建议使用S3而不是S4(http://google-styleguide.googlecode.com/svn/trunk/google-r-style.html).但是,我不知道S3方法/对象的确切定义.

Nic*_*bbe 81

大多数相关信息都可以通过查看?S3或找到?UseMethod,但简而言之:

S3指的是方法调度的方案.如果你使用的R用了一段时间,你会发现有print,predictsummary进行了大量不同类型的对象的方法.

在S3中,这通过以下方式工作:

  • 设置感兴趣的对象类(例如:对方法的调用的返回值glm具有类glm)
  • 提供一种方法与一般的名称(例如print),则一个点,然后将类名(例如: print.glm)
  • 为了实现这个目的,必须对这个通用名称做一些准备print工作,但是如果你只是想让自己符合现有的方法名称,你就不需要这个了(如果你做的话,请参阅我之前提到的帮助) ).

对于旁观者的眼睛,特别是新创建的时髦模型配件包的使用者来说,能够打字predict(myfit, type="class")比使用更方便predict.mykindoffit(myfit, type="class").

还有更多,但这应该让你开始.这种基于对象的属性(类)调度方法的方式存在很多缺点(而且纯粹主义者可能会在晚上醒来时很恐怖),但在很多情况下,它的工作正常.使用当前版本的R,已经实现了更新的方法(S4和参考类),但是大多数人仍然(仅)使用S3.


Ric*_*ton 50

要开始使用S3,请查看该median函数的代码.打字median在命令提示符下显示,其在它的身上一条线,即

UseMethod("median")
Run Code Online (Sandbox Code Playgroud)

这意味着它是一种S3方法.换句话说,您可以median为不同的S3类使用不同的函数.要列出所有可能的中位数方法,请键入

methods(median) #actually not that interesting.  
Run Code Online (Sandbox Code Playgroud)

在这种情况下,只有一个方法,即默认值,可以调用任何方法.您可以通过键入来查看该代码

median.default
Run Code Online (Sandbox Code Playgroud)

一个更有趣的例子是print函数,它有许多不同的方法.

methods(print)  #very exciting
Run Code Online (Sandbox Code Playgroud)

请注意,某些方法*的名称旁边有.这意味着它们隐藏在某个包的命名空间中.使用find找出他们是在哪个包.例如

find("acf")  #it's in the stats package
stats:::print.acf
Run Code Online (Sandbox Code Playgroud)


小智 37

来自http://adv-r.had.co.nz/OO-essentials.html:

R的三个OO系统在定义类和方法方面有所不同:

  • S3实现了一种称为泛型函数OO的OO编程风格.这与大多数编程语言不同,例如Java,C++和C#,它们实现消息传递OO.通过消息传递,消息(方法)被发送到对象,对象确定要调用的函数.通常,此对象在方法调用中具有特殊外观,通常出现在方法/消息的名称之前:例如canvas.drawRect("blue").S3是不同的.虽然计算仍然通过方法执行,但是一种称为泛型函数的特殊类型的函数决定调用哪个方法,例如drawRect(canvas,"blue").S3是一个非常随意的系统.它没有正式的类定义.

  • S4与S3的工作方式类似,但更为正式.S3有两个主要的区别.S4具有正式的类定义,它描述了每个类的表示和继承,并具有用于定义泛型和方法的特殊辅助函数.S4也有多个调度,这意味着泛型函数可以根据任意数量的参数类来选择方法,而不仅仅是一个.

  • 参考类,简称RC,与S3和S4完全不同.RC实现消息传递OO,因此方法属于类,而不是函数.$用于分隔对象和方法,因此方法调用看起来像canvas $ drawRect("blue").RC对象也是可变的:它们不使用R的通常的复制修改语义,而是在适当的位置进行修改.这使得他们更难以推理,但允许他们解决难以用S3或S4解决的问题.

还有另外一个系统不是OO,但重要的是在这里提一下:

  • 基本类型,作为其他OO系统基础的内部C级类型.基本类型主要使用C代码进行操作,但它们很重要,因为它们为其他OO系统提供构建块.


Jon*_*son 11

我来到这个问题,主要是想知道名字的来源.从这篇维基百科文章中可以看出,该名称是指R所基于的S编程语言的版本.其他答案中描述的方法调度方案来自S,并根据版本进行适当标记.


小智 9

尝试

methods(residuals)
Run Code Online (Sandbox Code Playgroud)

其中列出了"residuals.lm"和"residuals.glm".这意味着当您拟合线性模型,m和类型时residuals(m),将调用residuals.lm.当您拟合广义线性模型时,将调用residuals.glm.这种C++对象模型是颠倒的.在C++中,您定义了一个具有虚函数的基类,这些函数被派生的类重写.在R中,您定义了一个虚拟(也称为通用)函数,然后您决定哪些类将覆盖此函数(也称为定义方法).请注意,执行此操作的类不需要从一个公共超类派生.我不同意通常更喜欢S3而不是S4.S4有更多的形式(=更多的打字),这对某些应用来说可能太多了.但是,S4类可以像C++中的类或结构一样定义.您可以指定某个类的对象由字符串和两个数字组成,例如:

setClass("myClass", representation(label = "character", x = "numeric", y = "numeric"))
Run Code Online (Sandbox Code Playgroud)

使用该类的对象调用的方法可以依赖于具有这些成员的对象.这与S3类非常不同,后者只是一堆元素的列表.

使用S3和S4,您可以通过fun(object, args)而不是通过调用成员函数object$fun(args).如果您正在寻找类似后者的东西,请查看原型包.


Dav*_*fer 5

以下是根据Hadley Wickham(RStudio 首席科学家)的“Advanced R,第 2 版”(CRC Press,2019 年)对众多R 对象系统进行更新的快速概述,该文档基于有关对象的章节,在此处有一个 Web 表示面向编程

\n\n

高级 R 书籍封面

\n\n

2015 年的第一版在这里有一个 Web 展示,这里有关于 OO 的相应章节。

\n\n

面向对象系统的方法

\n\n

Hadley 定义了以下定义来区分两种不同的 OO 编程方法:

\n\n

函数式 OOP:方法(可调用代码段)属于泛型函数(不要与 Java/C#泛型方法混淆)。将这些方法视为位于全局查找表中。运行时系统根据函数名称和传递给该函数的一个或多个参数的类型(或对象类)找到要执行的方法(这称为“方法分派”)。从语法角度来看,方法调用可能看起来像普通的函数调用:myfunc(object, arg1, arg2)如果语言​​支持这一点。在 R 的 S3 中,通用函数的全名给出了(函数名,类)对。例如:mean.Date是计算日期平均值的方法。尝试methods("mean")列出具有函数名称的通用方法mean。例如,功能性 OOP 方法可以在 OO 先驱SmalltalkCommon Lisp 对象系统Julia中找到。Hadley 指出,“与 R 相比,Julia\xe2\x80\x99s 实现已完全开发且性能极高。”

\n\n

封装的 OOP:方法属于对象或类,方法调用通常类似于object.method(arg1, arg2). 这称为封装,因为对象封装了数据(字段)和行为(方法)。将该方法视为位于附加到对象或对象的类描述的查找表中。运行时根据方法名称以及可能的一个或多个参数的类型查找方法。这是“流行”的 OO 语言(如 C++、Java、C#)中采用的方法。

\n\n

在这两种情况下,如果支持继承(可能是),运行时可能会向上遍历类层次结构,直到找到调用查找键的匹配项。

\n\n

如何找出 R 对象属于哪个系统

\n\n
library(sloop) # formerly, "pryr"\notype(mtcars)\n#> [1] "S3"\n
Run Code Online (Sandbox Code Playgroud)\n\n

R 对象系统

\n\n

S3

\n\n
    \n
  • 函数式 OOP 方法。
  • \n
  • 哈德利认为最重要的系统。
  • \n
  • 最简单,最常见。R 使用的第一个面向对象系统。
  • \n
  • 与底座 R 一起提供,在整个底座 R 中使用。
  • \n
  • 依赖于约定而不是强制保证。
  • \n
  • 参见约翰·M·钱伯斯 (Chambers) 和特雷弗·J·哈斯蒂 (Trevor J Hastie)。1992.“S 中的统计模型”。Wadsworth & Brooks/Cole 高级书籍和软件。
  • \n
  • 详细信息请参见此处的“Advanced R,第二版”
  • \n
\n\n

S4

\n\n
    \n
  • 函数式 OOP 方法。
  • \n
  • 哈德利认为第三重要的系统。
  • \n
  • 重写S3,因此与S3类似,但更正式、更严格:它迫使你仔细思考程序设计。适合构建大型系统(例如Bioconductor项目)。
  • \n
  • 在基本“methods”包中实现。
  • \n
  • 请参阅:Chambers,John M. 1998。“数据编程:S 语言指南”。施普林格。
  • \n
  • 详细信息请参见此处的“Advanced R,第二版”
  • \n
\n\n

RC 又名“参考课程”

\n\n
    \n
  • 封装的 OOP 方法。
  • \n
  • 配有底座 R。
  • \n
  • 基于S4。
  • \n
  • RC 对象是特殊类型的 S4 对象,也是“可变的”。即,可以就地修改它们,而不是使用 R 通常的修改时复制语义。请注意,可变状态很难推理,并且是丑陋错误的来源,但可以在某些应用程序中带来更高效的代码。
  • \n
\n\n

R6

\n\n
    \n
  • 封装的 OOP 方法。
  • \n
  • 根据哈德利的说法,第二重要的系统。
  • \n
  • 可以在R6包中找到(使用安装library(R6)
  • \n
  • 与 RC 类似,但更轻且更快:它不依赖于 S4 或方法包。构建在 R 环境之上。还有:\n\n
      \n
    • 公共和私有方法
    • \n
    • 主动绑定(字段,当访问时,实际上调用一个方法)
    • \n
    • 跨包工作的类继承
    • \n
    • 方法(属于类的代码,可以通过self, private,访问实例super)和成员函数(分配给字段的函数,但不是方法,只是函数)
    • \n
  • \n
  • 提供一种标准化方法来转义 R 的“修改时复制”语义
  • \n
  • 请参阅包站点:“R6:R 的封装的面向对象编程”
  • \n
  • 详细信息请参见此处的“Advanced R,第二版”
  • \n
\n\n

其他的

\n\n

还有其他的,比如R.oo(类似于 RC)、proto(基于原型,想想 JavaScript)和Mutatr。然而,《Advanced R》说:

\n\n
\n

除了广泛使用的 R6 之外,这些系统主要具有理论意义。它们确实有自己的优势,但很少有 R 用户知道并理解它们,因此其他人很难阅读并为您的代码做出贡献。

\n
\n\n

请务必阅读“高级 R,第二版”有关权衡的章节。

\n