Controllo d'accesso

Precedentemente, abbiamo detto che ruby non ha funzioni, ma solo metodi. Comunque esistono più tipi di metodi . In questo capitolo introduciamo il controllo d'accesso.

Immaginate ciò che accade quando definiamo un metodo nel "livello più alto" , cioè fuori da una definizione di classe. Possiamo pensare ad un tale metodo come ad una funzione in un linguaggio più tradizionale come il C.

ruby> def quadrato(n)
    |   n * n
    | end
   nil
ruby> quadrato(5)
   25

Il nostro nuovo metodo sembrerà non appartere a nessuna classe, ma in effetti ruby lo mette nela classe Object , che è la superclasse di ogni altra. Come risultato, ogni oggetto ora dovrebbe essere in grado di poter usare quel metodo . Questa cosa risulterà essere vera, ma c'è un dettaglio: si tratta di un metodo privato di ogni classe. Discuteremo un po' di cosa significa questa dichiarazione più avanti, ma una delle conseguenza è che potrà essere invocato solo in “stile funzione”:

ruby> class Foo
    |   def quarta_potenza_di(x)
    |     quadrato(x) * quadrato(x)
    |   end
    | end
  nil
ruby> Foo.new.quarta_potenza_di 10
  10000

Non ci è permesso di applicare esplicitamente il metodo su di un oggetto:

ruby> "pesce".quadrato(5)
ERR: (eval):1: private method `square' called for "pesce":String

Ciò preserva in maniera intelligente la natura puramente OO di ruby (le funzioni sono ancora metodi degli oggetti, ma il ricevitore è implicitamenteself ) pur fornendo funzioni che possono essere scritte come in un linguaggio tradizionale.

Una disciplina mentale comune nella programmazione OO, alla quale abiamo fatto rigferimento in un capitolo precedente, riguarda la separazone tra specifica ed implementazione, o tra quali compiti si suppone che vengano svolti da un oggetto e come vengono effettivamente svolti. Il funzionamento interno di un oggetto dovrebbe generalmente essere mantenuto nascosto ai suoi utilizzatori; essi dovrebbero soltanto preoccuparsi di cosa entra e cosa esce, e fidarsi che l'oggetto sappia quelloche deve fare al suo interno. Ad esempio spesso è utile avere nelle classi dei metodi che il mondo esterno non vede, ma che sono usati internamente (e possono essere migliorati dal programmatore quando si vuole, senza cambiare il modo in cui gli uytenti vedono gli oggetti della classe). Nel seguente semplice esempio, pensate a engine come al lavoro interno ed invisibile della classe.

ruby> class Prova
    |   def volte_due(a)
    |     print a," volte due e' " ,engine(a),""
    |   end
    |   def engine(b)
    |     b*2
    |   end
    |   private:engine  # questo nasconde engine all'utente
    | end
   Test
ruby> test = Test.new
   #<Test:0x4017181c>
ruby> test.engine(6)
ERR: (eval):1: private method `engine' called for #<Test:0x4017181c>
ruby> test.volte_due(6)
6 volte due e' 12.
   nil

Potremmo esserci aspettati che test.engine(6) ritornasse 12, ma invece vediamo che engine è inaccessibile quando agiamo come utenti esterni a Prova. Solo ai metodi di Prova, come volte_due, viene permesso di usare engine. Abbiamo bisogno di passare attraverso l'interfaccia pubblica, che consiste nel metodo volte_due . Il programmatore che è responsabile di questa classe può cambiare engine liberamente (qui, forse cambiando b*2 con b+b, assumendo che ciò porti a prestazioni migliori) senza infastidire il modo in cui l'utente interagisce con gli oggetti Prova. Questo esempio ovviamente è troppo semplice per essere utile; i benfici del controllo d'accesso diventano più chiari quando cominciamo a creare classi più complesse ed interessanti .

Ti potrebbe interessare anche

commenta la notizia

C'è 1 commento
Francesco
Hai dubbi su questo articolo?