• Non ci sono risultati.

Proprietà di istanza ed ereditarietà

2.11 Ereditarietà

2.11.1 Proprietà di istanza ed ereditarietà

}

var cir:Circle = new Circle();

trace(cir.area()); // output: 3.141592653589793 var sq:Square = new Square();

trace(sq.area()); // output: 1

Poiché ogni classe definisce un tipo di dati, l'uso dell'ereditarietà crea una speciale relazione tra la classe base e la classe che la estende. Una sottoclasse possiede sempre tutte le proprietà della sua classe base, di conseguenza una qualsiasi istanza di una sottoclasse può sempre essere sostituita con un'istanza della classe base. Ad esempio, se un metodo definisce un parametro di tipo Shape, è consentito il passaggio di un argomento di tipo Circle, in quanto Circle è un'estensione di Shape, come indicato di seguito:

function draw(shapeToDraw:Shape) {}

var myCircle:Circle = new Circle(); draw(myCircle);

2.11.1 Proprietà di istanza ed ereditarietà

Una proprietà di istanza, sia che venga dichiarata con la parola chiave

function, var o const, viene ereditata da tutte le sottoclassi a condizione che essa non sia stata dichiarata con l'attributo private nella classe base.

Ad esempio, la classe Event in ActionScript 3.0 ha un numero di sottoclassi che ereditano proprietà comuni a tutti gli oggetti evento.

Per alcuni tipi di eventi, la classe Event contiene tutte le proprietà necessarie per la definizione dell'evento. Questi tipi di eventi non richiedono proprietà di istanza oltre a quelle definite nella classe Event. Esempi di tali eventi sono l'evento complete, che si verifica quando i dati vengono caricati correttamente, e l'evento connect, che si verifica quando viene stabilita una connessione di rete.

L'esempio seguente è un estratto della classe Event che illustra alcune delle proprietà e dei metodi ereditati dalle sottoclassi. Poiché vengono ereditate, le proprietà sono accessibili da una qualsiasi istanza di una sottoclasse.

public class Event {

public function get type():String;

public function get bubbles():Boolean;

...

public function stopPropagation():void {}

public function stopImmediatePropagation():void {}

public function preventDefault():void {}

public function isDefaultPrevented():Boolean {}

... }

Vi sono poi altri tipi di eventi che richiedono proprietà univoche non disponibili nella classe Event. Tali eventi vengono definiti utilizzando le sottoclassi della classe Event, in modo da consentire l'aggiunta di nuove proprietà alle proprietà già definite nella classe Event. Un esempio di tali sottoclassi è la classe MouseEvent, che aggiunge proprietà univoche per gli eventi associate ai movimenti o ai clic del mouse, quali gli eventi mouseMove e click.

L'esempio seguente è un estratto della classe MouseEvent che mostra la definizione di proprietà esistenti all'interno della sottoclasse, ma non nella classe base:

public class MouseEvent extends Event {

public static const CLICK:String= "click";

public static const MOUSE_MOVE:String = "mouseMove";

...

public function get stageX():Number {}

public function get stageY():Number {}

... }

 Specificatori del controllo di accesso ed ereditarietà

Se viene dichiarata con la parola chiave public, una proprietà risulta visibile al codice ovunque si trovi. Ciò significa che la parola chiave public, a differenza delle parole chiave private, protected e internal, non pone limiti all'ereditarietà delle proprietà.

Se viene dichiarata con la parola chiave private, una proprietà risulterà visibile solo nella classe che la definisce e non verrà ereditata da alcuna delle sottoclassi. Ciò non accadeva nelle versioni precedenti di ActionScript, dove la parola chiave private si comportava in modo simile alla parola chiave protected di ActionScript 3.0.

La parola chiave protected indica che una proprietà è visibile non solo all'interno della classe che la definisce, ma anche in tutte le sue sottoclassi. A differenza della parola chiave protected del linguaggio di programmazione Java, la parola chiave protected di ActionScript 3.0 non rende una proprietà visibile a tutte le altre classi dello stesso pacchetto. In ActionScript 3.0, solo le sottoclassi possono accedere a una proprietà dichiarata con la parola chiave protected. Inoltre, una proprietà protetta è visibile a una sottoclasse, sia che questa si trovi nello stesso pacchetto della classe base che in un pacchetto differente.

Per limitare la visibilità di una proprietà al pacchetto nel quale essa è stata definita, utilizzare la parola chiave internal oppure non utilizzare alcuno specificatore del controllo di accesso. Lo specificatore del controllo di accesso internal è lo specificatore predefinito che viene applicato quando non ne viene specificato alcuno. Se viene contrassegnata come internal, una proprietà verrà ereditata unicamente dalle sottoclassi che risiedono nello stesso pacchetto.

L'esempio seguente mostra come ogni specificatore del controllo di accesso può modificare l'ereditarietà nell'ambito dei pacchetti. Il codice seguente definisce una classe di applicazione principale chiamata AccessControl e due altre classi chiamate Base ed Extender. La classe Base si trova in un pacchetto denominato

foo, mentre la classe Extender, che è una sottoclasse della classe Base, si trova in un pacchetto chiamato bar. La classe AccessControl importa unicamente la classe Extender e crea un'istanza di Extender che tenta di accedere a una variabile chiamata str definita nella classe Base. La variabile str è dichiarata come

public, di conseguenza il codice viene compilato ed eseguito come nell'estratto seguente:

// Base.as in a folder named foo package foo

{

public class Base

{

public var str:String = "hello"; // change public on this line

}

}

// Extender.as in a folder named bar package bar

{

import foo.Base;

public class Extender extends Base

{

public function getString():String {

return str;

}

}

}

// main application class in file named AccessControl.as package

{

import flash.display.MovieClip;

import bar.Extender;

public class AccessControl extends MovieClip

{

public function AccessControl()

{

var myExt:Extender = new Extender();

trace(myExt.str);// error if str is not public

trace(myExt.getString()); // error if str is private or

internal

}

}

Per vedere come gli altri specificatori del controllo di accesso possono modificare la compilazione e l'esecuzione dell'esempio precedente, impostate lo specificatore del controllo di accesso alla variabile str su private, protected o internal, dopo avere eliminato o escluso mediante commento la seguente riga dalla classe AccessControl:

trace(myExt.str);// error if str is not public

 Sostituzione delle variabili non consentita

Le proprietà dichiarate con le parole chiave var o const vengono ereditate, ma non possono essere sostituite. Sostituire una proprietà significa ridefinirla in una sottoclasse. Il solo tipo di proprietà che è possibile sostituire sono i metodi, vale a dire le proprietà dichiarate con la parola chiave function. Nonostante non sia possibile sostituire una variabile di istanza, si può ottenere un risultato simile mediante la creazione di metodi getter e setter per la variabile di istanza, quindi sostituire tali metodi.