Частные члены в 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