Guida al Visual Basic .NET
Capitolo 23° - Membri Shared
Tutte le categorie di membri che abbiamo analizzato nei precedenti capitoli - campi, metodi, proprietà, costruttori - sono sempre state viste come appartenenti ad un oggetto, ad un'istanza di classe. Infatti, ci si riferisce ad una proprietà o a un metodo di uno specifico oggetto, dicendo ad esempio "La proprietà SideLength dell'oggetto A di tipo Cube vale 3, mentre quella dell'oggetto B anch'esso di tipo Cube vale 4.". La classe, ossia il tipo di una variabile reference, ci diceva solo quali membri un certo oggetto potesse esporre: ci forniva, quindi, il "progetto di costruzione" di un oggetto nella memoria, in cui si potevano collocare tali campi, tali metodi, tal'altre proprietà e via dicendo. Ora, un membro shared, o condiviso, o statico (termine da usarsi più in C# che non in VB.NET), non appartiene più ad un'istanza di classe, ma alla classe stessa. Mi rendo conto che il concetto possa essere all'inizio difficile da capire e da interiorizzare correttamente. Per questo motivo farò un esempio il più semplice, ma più significativo possibile. Riprendiamo la classe Cube, modificata come segue: Module Module1 Class Cube Private _SideLength As Single Private _Density As Single 'Questo campo è Shared, condiviso. Come vedete, 'per dichiarare un membro come tale, si pone la 'keyword Shared dopo lo specificatore di accesso. Questa 'variabile conterrà il numero di cubi creati 'dal nostro programma. 'N.B.: I campi Shared sono di default Private... Private Shared _CubesCount As Int32 = 0 Public Property SideLength() As Single Get Return _SideLength End Get Set(ByVal value As Single) If value > 0 Then _SideLength = value Else _SideLength = 1 End If End Set End Property Public Property Density() As Single Get Return _Density End Get Set(ByVal value As Single) If value > 0 Then _Density = value Else _Density = 1 End If End Set End Property Public ReadOnly Property SurfaceArea() As Single Get Return (SideLength ^ 2) End Get End Property Public ReadOnly Property Volume() As Single Get Return (SideLength ^ 3) End Get End Property Public ReadOnly Property Mass() As Single Get Return (Volume * Density) End Get End Property 'Allo stesso modo, la proprietà che espone il membro 'shared deve essere anch'essa shared Public Shared ReadOnly Property CubesCount() As Int32 Get Return _CubesCount End Get End Property 'Ogni volta che un nuovo cubo viene creato, _CubesCount 'viene aumentato di uno, per rispecchiare il nuovo numero 'di istanze della classe Cube esistenti in memoria Sub New() _CubesCount += 1 End Sub End Class Sub Main() Dim Cube1 As New Cube() Cube1.SideLength = 1 Cube1.Density = 2700 Dim Cube2 As New Cube() Cube2.SideLength = 0.9 Cube2.Density = 3500 Console.Write("Cubi creati: ") 'Notate come si accede a un membro condiviso: poiché 'appartiene alla classe e non alla singola istanza, vi si 'accede specificando prima il nome della classe, poi 'il comune operatore punto, e successivamente il nome 'del membro. Tutti i membri shared funzionano in questo 'modo Console.WriteLine(Cube.CubesCount) Console.ReadKey() End Sub End ModuleFacendo correre l'applicazione, si vedrà apparire a schermo il numero 2, poiché abbiamo creato due oggetti di tipo Cube. Come si vede, il campo CubesCount non riguarda un solo specifico oggetto, ma la totalità di tutti gli oggetti di tipo Cube, poiché è un dato globale. In generale, esso è di dominio della classe Cube, ossia della rappresentazione più astratta dell'essenza di ogni oggetto: per sapere quanti cubi sono stati creati, non si può interpellare una singola istanza, perchè essa non "ha percezione" di tutte le altre istanze esistenti. Per questo motivo CubesCount è un membro condiviso. Anche in questo caso c'è una ristretta gamma di casi in cui è opportuno scegliere di definire un membro come condiviso:
Classi SharedCome!?!? Esistono classi shared? Ebbene sì. Può sembrare assurdo, ma ci sono, ed è lecito domandarsi quale sia la loro funzione. Se un membro shared appartiene a una classe... cosa possiamo dire di una classe shared?A dire il vero, abbiamo sempre usato classi shared senza saperlo: i moduli, infatti, non sono altro che classi condivise (o statiche). Tuttavia, il significato della parola shared, se applicato alle classi, cambia radicalmente. Un modulo, quindi una classe shared, rende implicitamente shared tutti i suoi membri. Quindi, tutte le proprietà, i campi e i metodi appartenenti ad un modulo - ivi compresa la Sub Main - sono membri shared. Che senso ha questo? I moduli sono consuetamente usati, al di fuori delle applicazioni console, per rendere disponibili a tutto il progetto membri di particolare rilevanza o utilità, ad esempio funzioni per il salvataggio dei dati, informazioni sulle opzioni salvate, eccetera... Infatti è impossibile definire un membro shared in un modulo, poiché ogni membro del modulo lo è già di per sé: Module Module1 Shared Sub Hello() End Sub '... End SubIl codice sopra riportato provocherà il seguente errore: Methods in a Module cannot be declared 'Shared'.Inoltre, è anche possibile accedere a membri di un modulo senza specificare il nome del modulo, ad esempio: Module Module2 Sub Hello() Console.WriteLine("Hello!") End Sub End Module Module Module1 Sub Main() Hello() ' = Module2.Hello() Console.ReadKey() End Sub End ModuleQuesto fenomeno è anche noto col nome di Imports statico. A dir la verità esiste una piccola differenza tra classi statiche e moduli. Una classe può essere statica anche solo se tutti i suoi membri lo sono, ma non gode dell'Imports Statico. Un modulo, al contrario, oltre ad avere tutti i membri shared, gode sempre dell'Imports Statico. Per farla breve: Module Module2 Sub Hello() Console.WriteLine("Hello Module2!") End Sub End Module Class Class2 Shared Sub Hello() Console.WriteLine("Hello Class2!") End Sub End Class Module Module1 Sub Main() 'Per richiamare l'Hello di Class2, è sempre 'necessaria questa sintassi: Class2.Hello() 'Per invocare l'Hello di Module2, invece, basta 'questa, a causa dell'Imports Statico Hello() Console.ReadKey() End Sub End Module
C#, TypeScript, java, php, EcmaScript (JavaScript), Spring, Hibernate, React, SASS/LESS, jade, python, scikit, node.js, redux, postgres, keras, kubernetes, docker, hexo, etc...
|