Un handle di oggetto è un tipo che può contenere un riferimento a un oggetto. Con gli handle di oggetto è possibile dichiarare più variabili che fanno riferimento allo stesso oggetto fisico. Non tutti i tipi consentono di utilizzare gli handle degli oggetti. Nessuno dei tipi di dati primitivi, bool, int, float e così via, può avere handle di oggetti. I tipi di oggetto registrati dall'applicazione possono o meno consentire l'uso di maniglie, a seconda di come sono stati registrati. |
Uso generale
Un handle di oggetto viene dichiarato aggiungendo il simbolo @ al tipo di dati.
object@ obj_h; |
Questo codice dichiara l'handle dell'oggetto obj e lo inizializza a null, cioè non contiene un riferimento a nessun oggetto.
Nelle espressioni, le variabili dichiarate come handle di oggetti vengono utilizzate esattamente come gli oggetti normali. Occorre però tenere presente che gli handle degli oggetti non garantiscono che facciano effettivamente riferimento a un oggetto e se si tenta di accedere al contenuto di un oggetto in un handle che è nullo, viene sollevata un'eccezione.
object obj; |
Gli operatori come = o qualsiasi altro operatore registrato per il tipo di oggetto funzionano sull'oggetto reale a cui l'handle fa riferimento. Anche questi lanciano un'eccezione se l'handle è vuoto.
object obj; |
Quando è necessario eseguire un'operazione sull'handle attuale, si deve anteporre all'espressione il simbolo @. L'impostazione dell'handle dell'oggetto per puntare a un oggetto si esegue, ad esempio, in questo modo:
object obj; |
Si noti che il compilatore può spesso determinare implicitamente che è necessario l'handle dell'oggetto piuttosto che l'oggetto stesso. In questi casi non è necessario anteporre esplicitamente l'espressione con @.
Un handle di oggetto può essere confrontato con un altro handle di oggetto (dello stesso tipo) per verificare se puntano allo stesso oggetto o meno. Può anche essere confrontato con null, una parola chiave speciale che rappresenta un handle vuoto. Questo viene fatto usando l'operatore di identità, is.
object@ obj_a, obj_b; |
Si noti che gli operatori == e != eseguono un confronto di valori sugli oggetti a cui fanno riferimento gli handle, utilizzando gli overload degli operatori opEquals o opCmp. Tuttavia, se le espressioni sono precedute da @, gli operatori avranno la stessa funzione di is e !is.
Tempi di vita degli oggetti
La durata di vita di un oggetto è normalmente quella dell'ambito in cui la variabile è stata dichiarata. Ma se un handle esterno all'ambito viene impostato per fare riferimento all'oggetto, quest'ultimo continuerà a vivere finché tutti gli handle dell'oggetto non verranno rilasciati.
object@ obj_h; |
Relazioni tra oggetti e polimorfismo
Gli handle degli oggetti possono essere usati per scrivere codice comune per tipi correlati, tramite l'ereditarietà o le interfacce. In questo modo, un handle a un'interfaccia può memorizzare i riferimenti a tutti i tipi di oggetti che implementano quell'interfaccia; allo stesso modo, un handle a una classe base può memorizzare i riferimenti a tutti i tipi di oggetti che derivano da quella classe.
interface I {} |
Handle const
A volte è necessario mantenere handle per oggetti che non dovrebbero essere modificati. Questo viene fatto anteponendo al tipo il prefisso "const", ad esempio:
obj @a; // handle to modifiable object |
Un handle a un oggetto non modificabile può fare riferimento sia a oggetti modificabili che a oggetti non modificabili, ma lo script non consentirà di modificare l'oggetto attraverso quell'handle, né di passare l'handle a un altro handle che consenta modifiche.
Questa sintassi non deve essere confusa con gli handle che sono di sola lettura, cioè l'handle non può essere riassegnato per riferirsi a un oggetto diverso. Gli handle di sola lettura come questo vengono dichiarati aggiungendo la parola chiave 'const' come suffisso dopo il simbolo '@'.
obj @const c = obj(); // read-only handle to a modifiable object |
Un handle di sola lettura può essere inizializzato solo quando viene dichiarato.