Можно ли изменить значение функции 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
функции не экспортируются, то это тоже относительно аккуратно в пространстве имен.