2011-11-16 10 views
10

È possibile avere campi membri privati ​​all'interno di una classe di riferimento R. Giocando con alcuni degli esempi online che ho:Membri privati ​​nella classe di riferimento 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 

Odio il fatto che posso aggiornare la bilancia direttamente. Forse che il vecchio OO puro in me, mi piacerebbe davvero essere in grado di rendere l'equilibrio privato, almeno non impostabile dall'esterno della classe.

Pensieri

+0

Il pacchetto/framework R6 ha campi privati ​​e metodi compilati (e si dice che siano più performanti). – petermeissner

risposta

3

Questa risposta non funziona con R> 3.00, quindi non utilizzarlo!

Come è stato detto, non è possibile avere campi membri privati. Tuttavia, se si utilizza il metodo di inizializzazione, il saldo non viene visualizzato come campo. Ad esempio,

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

Come prima, creeremo un caso:

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

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

Come ho già detto, non è veramente privata, dal momento che si può ancora fare:

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

R non è quel tipo di linguaggio. Non c'è idea di privato o pubblico.

+0

Prendo nota del downvote con interesse. Se ho sbagliato, per favore, dimmi come. –

+0

Penso che somene stia sparando al messaggero. Qual è il valore delle Classi in R se non mi consentono di incapsulare e controllare lo stato? O formulato in modo diverso quello che erano (classi) destinati a risolvere – akaphenom

+1

C'è ancora un valore in OOP senza protezione di accesso. Penso che uno abbia solo bisogno di una mentalità diversa. –

2

Per risolvere il problema della privacy, creo una propria classe, "Privata", che ha nuovi metodi per accedere all'oggetto, ovvero $ e [[. Questi metodi generano un errore se il client tenta di accedere al membro 'privato'. I membri privati ​​sono identificati dal nome (periodo principale). Poiché gli oggetti di riferimento sono ambienti in R, è possibile ovviare a questo problema, ma in questo momento è la mia soluzione e ritengo più conveniente utilizzare i metodi get/set forniti dalla classe. Quindi questa è più la soluzione 'difficile da impostare-da-fuori-classe' alla domanda.

L'ho organizzato all'interno di un pacchetto R in modo che il codice seguente utilizzi tale pacchetto e modifichi l'esempio precedente in modo che un'assegnazione a tb$.balance produca un errore. Io uso anche la funzione Class che è solo un wrapper intorno a setRefClass quindi questo è ancora nell'ambito delle classi di riferimento di R fornite dal pacchetto metodi e utilizzate nella domanda.

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 
Problemi correlati