2015-01-19 2 views
2

В настоящее время я изучаю возможности R's Reference Class, и я пытаюсь склонить голову к настраиваемым функциям доступа. Ручные состояния для поля, что:Определение функции доступа для ссылочного класса

элемент в списке может быть альтернативно функцией аксессор, функция одного аргумента, который возвращает поле, если вызывается без аргумента или устанавливает его в значение в противном случае. Функции Accessor используются внутри и для межсистемного интерфейса приложений. Их определение следует правилам для методов записи для класса: они могут ссылаться на другие поля и могут вызывать другие методы для этого класса или его суперклассов. См. Раздел «Внедрение» для внутреннего механизма, используемого функциями доступа .

Все, что я смог найти, это использовать функции доступа в контексте file storage. Привыкнув к частным внутренним переменным и входных валидаций я бы сказал, что это где проверки входных данных должны быть, см пример ниже:

Account <- 
    setRefClass("Account", 
       fields = list(data = "list", 
          balance = 
           function(value){ 
           if (missing(value)){ 
            return(data$balance) 
           }else{ 
            if (!is.numeric(value)) 
            stop("You can only set the balance to a numeric value!") 
            data$balance <<- value 
           } 
           }), 
       methods = list(
       withdraw = function(x) { 
        balance <<- balance - x 
       }, 
       deposit = function(x) { 
        balance <<- balance + x 
       } 
      )) 

Это работает, как ожидалось:

> a <- Account$new(balance = 0) 
> 
> a$deposit(10) 
> a$balance 
[1] 10 
> 
> a$withdraw(1) 
> a$balance 
[1] 9 
> 
> a$balance <- "a" 
Error in (function (value) : 
    You can only set the balance to a numeric value! 

Что я хотел бы знать, есть ли причина для этого, поскольку это кажется естественным подходом, но не упомянутым в руководстве? Есть ли хороший способ полностью скрывать переменную данных, например. используя .self <- local({data = list(); .self}) в некоторый момент.

ответ

0

Я тоже борется с этим, и кажется, что нет возможности полностью скрывать данные. Одна вещь, которую я заметил с вашим примером является то, что вы можете вручную изменить значение баланса по телефону:

a <- Account$new(balance = 0) 
a$data$balance<-"a" 
a$balance 
#> [1] "a" 

Причина, по-прежнему можно манипулировать по этой причине я подозреваю, что это не рекомендуется. Когда в руководстве описываются функции доступа, они, похоже, ссылаются на те, которые вы получаете, если хотите использовать $ accessor (описано в руководстве). Пример ниже:

Account <- 
    setRefClass("Account", 
       fields = list(balance = "numeric"), 
       methods = list(
       withdraw = function(x) { 
        balance <<- balance - x 
       }, 
       deposit = function(x) { 
        balance <<- balance + x 
       } 
      )) 
Account$accessors("balance") 
a<-Account$new("balance"=0) 
# you can now get and set the balance with getBalance() and setBalance(x). 
# (it automatically capitalizes your field name) 
a$setBalance(10) 
a$getBalance() 
# [10] 

Наконец, вы всегда можете создать и установить методы getBalance()/setBalance(x) вручную, если вы хотите добавить дополнительные проверки в methods аргумент для setClassRef. Большинство из этого выведено из документации для setClassRef. See this link on stackoverflow below which discusses Private Members.

+0

Я видел сообщение, я считаю, что существует путь, который в пределах R заставляет переменные вести себя в частной манере. @hadley предлагает в своей превосходной книге Advanced R в [упражнении] (http://adv-r.had.co.nz/OO-essentials.html): * Используйте полевую функцию, чтобы предотвратить баланс аккаунта непосредственно манипулировать *. Он предлагает использовать поле «.balance» и функцию поля баланса, но на самом деле не скрывает это поле. Я попытался использовать 'balance = local ({balance <- NULL; my_func() ...})', но это эквивалентно [статической переменной] (http://en.wikipedia.org/wiki/Static_variable) , –

Смежные вопросы