我很早以前在Coursera上的Johns Hopkins MOOC R编程中学到了这种方式。想法是返回在父函数的作用域中定义的函数列表。例如:
newString <- function(s) {
l <- nchar(s)
return(list(
get = function() return(s),
len = function() return(l),
concate = function(cat) {
s <<- paste0(s, cat)
l <<- nchar(s)
},
find = function(pattern) return(grepl(pattern, s)),
substitute = function(pattern, sub) {
s <<- gsub(pattern, sub, s)
l <<- nchar(s)
}
))
}
此函数返回可以操纵项目“ s”的函数/方法的列表。我可以“新建”这个“对象”并调用父函数:
my <- newString("hellow")
将{methods}与$
一起使用就像是OOP。
my$get()
# [1] "hellow"
my$len()
# [1] 6
my$substitute("w$", "")
my$get()
# [1] "hello"
my$len()
# [1] 5
my$concate(", world")
my$get()
# [1] "hello, world"
my$find("world$")
# [1] TRUE
要直接打印“对象”,我们可以看到它是功能列表。所有这些功能都位于项目0x103ca6e08
所在的同一环境s
中。
my
# $get
# function ()
# return(s)
# <bytecode: 0x1099ac1e0>
# <environment: 0x103ca6e08>
#
# $len
# function ()
# return(l)
# <bytecode: 0x109a58058>
# <environment: 0x103ca6e08>
#
# $concate
# function (cat)
# {
# s <<- paste0(s, cat)
# l <<- nchar(s)
# }
# <bytecode: 0x1074fd4e8>
# <environment: 0x103ca6e08>
#
# $find
# function (pattern)
# return(grepl(pattern, s))
# <bytecode: 0x1076c8470>
# <environment: 0x103ca6e08>
#
# $substitute
# function (pattern, sub)
# {
# s <<- gsub(pattern, sub, s)
# l <<- nchar(s)
# }
# <bytecode: 0x1077ad270>
# <environment: 0x103ca6e08>
那么这种编程风格(?)被认为是OOP还是类似OOP?与S3 / S4有什么区别?
感谢@ G.Grothendieck,@ r2evans和@Jozef。 R中的scoping
的演示文档说,由于R中的作用域规则,“功能可以封装状态信息”。RC系统“使用环境”,所以我认为我所做的与原始RC系统相似
“对象是具有函数的数据。闭包是具有数据的函数。” -约翰·库克(John D. Cook)
闭包之所以得名,是因为它们封闭了父函数的环境并且可以访问其所有变量。
在http://adv-r.had.co.nz/Functional-programming.html#closures中,我发现最合适的名称是闭包。
答案 0 :(得分:4)
您在此处尝试做的事情使我想起reference classes
或R6
包对该概念的替代实现-本质上是试图使OO系统类似于其他“经典” OOP语言(例如Java):
参考类别:
R6
例如,您可以这样定义R6类:
library(R6)
Person <- R6Class("Person",
public = list(
name = NULL,
hair = NULL,
initialize = function(name = NA, hair = NA) {
self$name <- name
self$hair <- hair
self$greet()
},
set_hair = function(val) {
self$hair <- val
},
greet = function() {
cat(paste0("Hello, my name is ", self$name, ".\n"))
}
)
)
然后可以从该类创建一个实例:
ann <- Person$new("Ann", "black")