Можно ли изменить значение функции R6? (Хороший стиль ООП программирования?)

Я пришел из C++ фона, пытаясь использовать его для программирования R OOP с пакетом R6.
Рассмотрим следующую типичную ситуацию при написании большого кода ООП. - У вас есть класс, в котором у вас есть несколько (возможно, много) функций, каждая из которых также может быть довольно сложной и иметь много строк кода:

# 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

Нет, это не так. Как видно из вывода выше, функция не была изменена.

Любой совет?

2 ответа

Решение

Благодаря приведенному выше комментарию Гротендика есть разумное решение, чтобы заставить его работать.

Вместо этого:

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

напишите это:

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

Этот код теперь может быть записан в отдельном файле, как первоначально хотелось.

Я все еще задаюсь вопросом - действительно ли вышеописанный способ является обычной (наилучшей) практикой написания больших ООП-кодов в сообществе R? (выглядит немного странно для меня).
Если нет, то что это такое (помимо использования source()) - чтобы включить совместное кодирование и контроль исходного кода для отдельных частей (функций) класса?

Я приехал сюда также в поисках лучшей практики R6. Один из способов, который я видел ( здесь), - определить функции в другом месте как обычные функции 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 функции не экспортируются, то это тоже относительно аккуратно в пространстве имен.

Другие вопросы по тегам