Частные члены в R Reference Class

Возможно ли иметь частные поля-члены внутри ссылочного класса R. Играя с некоторыми из онлайн-примеров, у меня есть:

> Account <- setRefClass(    "ref_Account"
>      , fields = list(
>       number = "character"
>       , balance ="numeric")
>      , methods = list( 
>     deposit <- function(amount) {
>       if(amount < 0)   {
>         stop("deposits must be positive")
>       }
>       balance <<- balance + amount
>     }
>     , withdraw <- function(amount) {
>       if(amount < 0)   {
>         stop("withdrawls must be positive")
>       }
>       balance <<- balance - amount
>     }       
>   ) )
> 
> 
> tb <- Account$new(balance=50.75, number="baml-029873") tb$balance
> tb$balance <- 12 
> tb$balance

Я ненавижу тот факт, что я могу напрямую обновить баланс. Возможно, что старое чистое ОО во мне, я действительно хотел бы сделать баланс частным, по крайней мере не устанавливаемым извне класса.

Мысли

Ответ 1

Этот ответ не работает с R > 3.00, поэтому не используйте его!

Как уже упоминалось, вы не можете иметь частные поля пользователя. Однако, если вы используете метод initialize, баланс не отображается как поле. Например,

Account = setRefClass("ref_Account", 
                       fields = list(number = "character"),
                       methods = list(
                           initialize = function(balance, number) {
                               .self$number = number
                               .self$balance = balance
                           })

Как и прежде, мы создадим экземпляр:

tb <- Account$new(balance=50.75, number="baml-0029873")
##No balance
tb

Reference class object of class "ref_Account"
Field "number":
[1] "baml-0029873"

Как я уже упоминал, он не является действительно закрытым, поскольку вы все еще можете:

R> tb$balance
[1] 50.75
R> tb$balance = 12 
R> tb$balance
[1] 12

Ответ 2

R - не такой язык. Нет понятия частного или публичного.

Ответ 3

Чтобы решить проблему конфиденциальности, я создаю собственный класс "Private", который имеет новые методы для доступа к объекту, т.е. $ и [[. Эти методы будут вызывать ошибку, если клиент пытается получить доступ к члену 'private'. Частный член идентифицируется по названию (ведущий период). В качестве эталонных объектов в среде R можно обойти это, но это мое решение в это время, и я считаю более удобным использовать методы get/set, предоставляемые классом. Таким образом, это более сложное решение "трудно устанавливаемое извне" для этого вопроса.

Я организовал это внутри R-пакета, поэтому следующий код использует этот пакет и изменяет приведенный выше пример таким образом, что присвоение tb$.balance вызывает ошибку. Я также использую функцию Class, которая является всего лишь оберткой вокруг setRefClass, поэтому она все еще находится в области R ссылочных классов, предоставляемых пакетом методов и используемых в вопросе.

devtools::install_github("wahani/aoos")
library("aoos")

Account <- defineRefClass({
    Class <- "Account"
    contains <- "Private"

    number <- "character"
    .balance <- "numeric"

    deposit <- function(amount) {
        if(amount < 0) stop("deposits must be positive")
        .balance <<- .balance + amount
    }

    withdraw <- function(amount) {
        if(amount < 0) stop("withdrawls must be positive")
        .balance <<- .balance - amount
    }
})

tb <- Account(.balance = 50.75, number = "baml-029873") 
tb$.balance # error
tb$.balance <- 12 # error