sabato 1 maggio 2010

Java: accesso protetto

L'incapsulamento dei dati in Java suggerisce di assegnare ai campi dell'istanza l'identificatore private e ai metodi di accesso l'identificatore public (la visibilità di una funzione privata, infatti, è limitata solo all'interno della classe). Ciò costituisce l'interfaccia pubblica della classe, il set di metodi che è possibile invocare, dall'esterno, sugli oggetti della classe.
Poiché una sottoclasse non può accedere ai dati privati della sua superclasse Java introduce l'identificatore protected per rendere fattibile l'accesso. Si osservino ad esempio le seguenti classi:

class A {
   public A() {
      this.a='a';
   }
   private char a;
}

class B extends A{
   public B() {
      this.b='b';
      this.previousChar=this.a;
   }
   private char b;
   private char previousChar;
}

Il campo dati a della classe A è privato e l'accesso non è possibile! Eclipse riporta: "The field A.a is not visible."! Per agevolare l'accesso è sufficiente modificare il campo dell'istanza da private a protected:

class A {
   public A() {
      this.a='a';
   }
   protected char a;
}

class B extends A{
   public B() {
      this.b='b';
      this.previousChar=this.a;
   }
   private char b;
   private char previousChar;
}

Bisogna analizzare attentamente la possibilità di prevedere un campo dell'istanza protetto. C'è il rischio che a partire da quella classe che ne fa uso vengano poi generate altre classi per il solo gusto di accedere al campo protetto dell'istanza! Si può limitare il fenomeno dichiarando un metodo che accede al campo protetto con l'identificatore protected: un metodo protetto è invocabile solo da una classe derivata (chi deriva una classe dovrebbe conoscerne i metodi anche se usando la riflessione si può comunque aggirare l'ostacolo).

class A {
   public A() {
      this.a='a';
   }
   protected char getA() {
      return a;
   }
   private char a;
}

class B extends A{
   public B() {
      this.b='b';
      this.previousChar=this.getA();
   }
   private char b;
   private char previousChar;
}

Nessun commento:

Posta un commento