【问题标题】:Using S3 Constructors in R在 R 中使用 S3 构造函数
【发布时间】:2018-01-04 03:46:59
【问题描述】:

今天早些时候我正在查看一些代码 (https://www.r-bloggers.com/building-your-own-blockchain-in-r/),其中有人以我以前从未见过的方式定义 S3 函数并且喜欢这种视觉风格,但从未在 R 代码的其他任何地方看到它并且想要找出原因。

他们定义了一些看起来像的 S3 类

my_class <- function(){
  # set some attributes
  inst <- list(foo = "bar")

  # define a function
  inst$change_foo <- function(what) {inst$foo <- what}

  # get S3 class right
  class(inst) <- "my_class"
  inst <- list2env(inst)
  inst
}

基本上,令我震惊的是,这个人试图让 R 的通用函数 S3 OO 系统看起来像更标准的消息传递 OO 系统(如 Python、Java 等),其中方法属于类。

我的感觉是这在 R 中可能是不好的做法,因为

baz <- my_class()
baz$change_foo("baz")

并没有真正做到你认为的那样。诚然,我的理解是,在其他面向对象的语言中,baz$change_foo 实际上绑定到my_class 的那个实例,所以它总是会编辑baz

在 R 中,这种绑定实际上并没有发生,因此 my_class 定义中的 inst 可以找到与 baz 不同的 inst(如果它恰好在环境中)。

只有list2env 调用才能使这里的事情保持整洁,而在更复杂的示例中可能会搞砸。

我确实喜欢这段代码可视化地为my_class 封装函数的方式,所以我很好奇我是否在这里做一些事情,或者我是否正在为无所事事而烦恼。 Stack Overflow 的居民们,你们怎么说?这是好还是坏的风格?

【问题讨论】:

  • 我并没有在你的帖子中找到问题
  • 这个有趣但基于意见的问题在community.rstudio.com 上会做得更好。 StackOverflow 更适合解决有关如何使代码工作的问题。

标签: r oop r-s3


【解决方案1】:

我假设问题是评论该方法以及沿着这些思路存在的内容。

首先请注意,这可以通过在 myClass 函数本身中使用运行时环境来简化,而不是创建一个新环境:

myClass <- function() {
   foo <- "bar"
   change_foo <- function(what) foo <<- what
   environment()
}

# test
baz <- myClass()
baz$change_foo("baz")
baz$foo
## [1] "baz"

从 R 的基本功能构建 OO 系统的想法已经存在多年。例如,R 附带的这个演示从早期就已经存在:

demo("scoping")

在使用环境的 R 或 R 包中也有许多 OO 系统。例如,查看 R 本身中的引用类(来自 R ?ReferenceClasses)和 CRAN 包 proto、R.oo 和 R6。在 S3 和 S4 之后的 R 2.12 中引入了参考类。 proto 和 R.oo 于 2005 年首次发布,R6 于 2014 年发布。ggplot2 最初是用 proto 编写的,R.oo 的作者使用它编写了许多包。gWidgets2 包是使用 S3 和引用类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-24
    • 2014-09-10
    • 2017-04-01
    相关资源
    最近更新 更多