1

我今天早些时候正在查看一些代码(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 中,该绑定实际上并没有发生,因此定义inst中的可能会发现与它恰好在环境中不同的情况。my_classinstbaz

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

我确实喜欢这段代码在视觉上封装函数的方式my_class,所以我很好奇我是否在这里做一些事情,或者我是否正在全力以赴。Stack Overflow 的居民们,你们怎么说?这是好还是坏的风格?

4

1 回答 1

0

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

首先请注意,这可以通过在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 和参考类。

于 2018-01-04T05:15:14.563 回答