是否可以改变R6功能的值? (好风格的OOP编程?)

时间:2017-07-26 15:43:48

标签: r function oop closures r6

我来自C ++背景,尝试将其用于R6封装的R OOP编程。
编写大型OOP代码时,请考虑以下典型情况。 - 你有一个类,你有几个(可能很多)函数,每个函数也可能非常复杂并且有很多代码行:

# 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中做类似的事情,比如:首先,在上面的代码中声明一个函数,然后尝试分配&#34;实际的长而复杂的&#34;以后的代码(稍后我将放在一个单独的文件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

不,它没有.-从上面的输出可以看出,该功能尚未改变。

有什么建议吗?

2 个答案:

答案 0 :(得分:1)

感谢Grothendieck上面的评论,有一个合理的解决方法可以让它发挥作用。

而不是:

# CTest-Do1_doesnotwork.R
cTest$fDo1 <- function() { 
    ... 
}     

写下这个:

# CTest-Do1_works.R  
cTest$set(
  overwrite = TRUE, "public", "fDo1",    
  function() {  
      ...
  }
)

此代码现在可以根据需要在单独的文件中编写。

我仍然想知道 - 以上描述的方式实际上是在R社区中编写大型OOP代码的常见(最佳)实践吗? (看起来有点奇怪) 如果不是,它是什么(除了使用source())? - 以便为类的单独部分(功能)启用协作编码和源代码控制?

答案 1 :(得分:1)

我来这里也在寻找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
}

我不知道它是最佳实践还是高效,但是类定义看起来很整洁,如果cTestfDo1函数没有导出,那么它相对整齐在命名空间中也是如此。