【问题标题】:Is it possible to change the value of R6 function ? (Good style OOP programming?)是否可以更改 R6 函数的值? (好的风格的 OOP 编程?)
【发布时间】:2018-01-02 01:21:33
【问题描述】:

我来自 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 中做类似的事情,例如:首先,在上面的代码中声明一个函数,然后,稍后尝试将“实际长而复杂”的代码分配给它(稍后我会放入单独的文件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

不,它没有。- 从上面的输出中可以看出,函数没有改变。

有什么建议吗?

【问题讨论】:

  • "如果您使用 C++(Java 等)编程,编写此类代码的常规方法是:首先,在 .h 文件中声明函数,然后为每个复杂函数创建 .c 文件,你在哪里定义你的函数”——这实际上并不适用于 Java。对于一种语言来说,拥有单独的头文件和实现文件实际上并不常见。

标签: r function oop closures r6


【解决方案1】:

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

而不是这个:

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

写这个:

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

现在可以按照最初的要求将此代码写入单独的文件中。

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

【讨论】:

    【解决方案2】:

    我来这里也是为了寻找 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 函数,那么它在命名空间中也相对整洁。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-14
    • 2010-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多