是否可以更改 R6 函数的值? (良好的 OOP 编程风格?)
Is it possible to change the value of R6 function ? (Good style OOP programming?)
我来自 C++ 背景,试图将它用于 R6 包的 R OOP 编程。
在编写大型 OOP 代码时,请考虑以下典型情况。 -
你有一个class,里面有几个(可能很多)函数,每个函数也可能相当复杂,有很多行代码:
# file CTest.R
cTest <- R6Class(
"CTest",
public = list(
z = 10,
fDo1 = function() {
# very long and complex code goes here
self$z <- self$z*2; self$z
},
fDo2 = function() {
# another very long and complex code goes here
print(self)
}
)
) #"CTest"
当然,您不想将所有冗长的函数和各种函数放在同一个 (CTest.R
) 文件中 - 它会变得杂乱无章且难以管理。
如果您使用 C++ 编程,编写此类代码的正常方法是:首先,您在 .h
文件中声明函数,然后为每个复杂函数创建 .c
文件,并在其中定义函数。这使得协作代码编写成为可能,包括高效的源代码控制。
所以,我尝试在 R 中做一些类似的事情,比如:首先,像上面的代码一样声明一个函数,然后,稍后尝试将 "actual long and complex" 代码分配给它(稍后我将放在一个单独的文件中 CTest-Do1.R
):
cTest$f <- function() {
self$z <- self$z*100000; self$z
}
现在我测试它是否有效:
> tt <- cTest$new(); tt; tt$fDo1(); tt
<CTest>
Public:
clone: function (deep = FALSE)
fDo1: function ()
fDo2: function ()
z: 10
[1] 20
<CTest>
Public:
clone: function (deep = FALSE)
fDo1: function ()
fDo2: function ()
z: 20
不,它没有。- 从上面的输出可以看出,函数没有改变。
有什么建议吗?
感谢 Grothendieck 上面的评论,有一个合理的解决方法可以让它工作。
而不是这个:
# CTest-Do1_doesnotwork.R
cTest$fDo1 <- function() {
...
}
这样写:
# CTest-Do1_works.R
cTest$set(
overwrite = TRUE, "public", "fDo1",
function() {
...
}
)
此代码现在可以按照最初的要求写在单独的文件中。
我仍然想知道 - 上面描述的方式实际上是在 R 社区中编写大型 OOP 代码的常见(最佳)实践吗? (我觉得有点奇怪)。
如果不是,它是什么(除了使用 source()
)? - 以便为 class 的单独部分(功能)启用协作编码和源代码控制?
我也是来这里寻找R6最佳实践的。我见过的一种方法 (here) 是将其他地方的函数定义为普通 R 函数,并根据需要传入 self、private 等
cTest<- R6::R6Class("CTest",
public = list(
fDo1 = function()
cTestfDo1(self),
fDo2 = function(x)
cTestfDo2(self, private, x)
))
还有其他地方有
cTestfDo1 <- function(self) {
self$z <- self$z*2; self$z
}
和其他地方
cTestfDo2 <- function(self, private, x) {
self$z * private$q + x
}
等等
我不知道这是最佳实践还是高效,但 class 定义看起来很整洁,如果 cTestfDo1
函数未导出,那么它在命名空间中也相对整洁.
我来自 C++ 背景,试图将它用于 R6 包的 R OOP 编程。
在编写大型 OOP 代码时,请考虑以下典型情况。 -
你有一个class,里面有几个(可能很多)函数,每个函数也可能相当复杂,有很多行代码:
# file CTest.R
cTest <- R6Class(
"CTest",
public = list(
z = 10,
fDo1 = function() {
# very long and complex code goes here
self$z <- self$z*2; self$z
},
fDo2 = function() {
# another very long and complex code goes here
print(self)
}
)
) #"CTest"
当然,您不想将所有冗长的函数和各种函数放在同一个 (CTest.R
) 文件中 - 它会变得杂乱无章且难以管理。
如果您使用 C++ 编程,编写此类代码的正常方法是:首先,您在 .h
文件中声明函数,然后为每个复杂函数创建 .c
文件,并在其中定义函数。这使得协作代码编写成为可能,包括高效的源代码控制。
所以,我尝试在 R 中做一些类似的事情,比如:首先,像上面的代码一样声明一个函数,然后,稍后尝试将 "actual long and complex" 代码分配给它(稍后我将放在一个单独的文件中 CTest-Do1.R
):
cTest$f <- function() {
self$z <- self$z*100000; self$z
}
现在我测试它是否有效:
> tt <- cTest$new(); tt; tt$fDo1(); tt
<CTest>
Public:
clone: function (deep = FALSE)
fDo1: function ()
fDo2: function ()
z: 10
[1] 20
<CTest>
Public:
clone: function (deep = FALSE)
fDo1: function ()
fDo2: function ()
z: 20
不,它没有。- 从上面的输出可以看出,函数没有改变。
有什么建议吗?
感谢 Grothendieck 上面的评论,有一个合理的解决方法可以让它工作。
而不是这个:
# CTest-Do1_doesnotwork.R
cTest$fDo1 <- function() {
...
}
这样写:
# CTest-Do1_works.R
cTest$set(
overwrite = TRUE, "public", "fDo1",
function() {
...
}
)
此代码现在可以按照最初的要求写在单独的文件中。
我仍然想知道 - 上面描述的方式实际上是在 R 社区中编写大型 OOP 代码的常见(最佳)实践吗? (我觉得有点奇怪)。
如果不是,它是什么(除了使用 source()
)? - 以便为 class 的单独部分(功能)启用协作编码和源代码控制?
我也是来这里寻找R6最佳实践的。我见过的一种方法 (here) 是将其他地方的函数定义为普通 R 函数,并根据需要传入 self、private 等
cTest<- R6::R6Class("CTest",
public = list(
fDo1 = function()
cTestfDo1(self),
fDo2 = function(x)
cTestfDo2(self, private, x)
))
还有其他地方有
cTestfDo1 <- function(self) {
self$z <- self$z*2; self$z
}
和其他地方
cTestfDo2 <- function(self, private, x) {
self$z * private$q + x
}
等等
我不知道这是最佳实践还是高效,但 class 定义看起来很整洁,如果 cTestfDo1
函数未导出,那么它在命名空间中也相对整洁.