A28. Operatori
Gli operatori speciali metodi in grado di eseguire operazioni artitmetiche e non su un determinato tipo. Gli operatori più comuni sono
+, -, *, /, \, =, mod e & e sono applicabili su qualsiasi valore numerico. È possibile usare questi ultimi su tipi presenti nel Framework,
come Int16 o Double, ma se si dovesse attuare un'operazione tra strutture e, perchè no?, tra classi definite dal programmatore? In questo
capitolo illustrerò come sia possibile definire operatori "su misura" per i propri tipi.
Un operatore viene definito in questo modo:
Un operatore viene definito in questo modo:
È essenziale che sia dichiarato come Shared, statico, poichè ovviamente appartiene alla classe come tipo e non ad ogni singola istanza (per farla breve, non si potrebbero scrivere cose come Frazione.+ o Frazione.-). Ogni operatore può essere unario o binario, a seconda che operi su uno o due parametri, ma non deve mai avere più di tre parametri (non esistono operatori ternari come nel C, ? :): inoltre il tipo restituito non deve per forza essere lo stesso della struttura in cui viene definito (ad esempio, un confronto di uguaglianza fra due Int16 restituisce un tipo Booleano). Altra cosa importante da tenere presente è che il simbolo dell'operatore non può essere definito arbitrariamente, ma deve essere uno tra questi: +, -, *, /, \, ^, &, <<, >>, =, <=, =>, <, >, Like, Mod, And, Or, Xor, Not, CType, IsTrue, IsFalse. Ecco un codice di esempio:Shared Operator [simbolo dell'operatore]([parametri])As [tipo]' Codice dell'operatore End Operator
È da notare che le espressioni come (A+B) o (A-B) restituiscano anch'esse un tipo frazione, che gode di tutti i metodi in esso definiti. Inoltre, bisogna specificare che anche le strutture possono accettare dei costruttori che rendono molto più efficiente l'assegnamento di valori: tuttavia, dato che le strutture sono tipi value e non reference, non devono per forza essere inizializzate da un costruttore. Il semplice dichiarare "As [Struttura]" rende la variabile utilizzabile. Vorrei far notare anche un altro piccolo dettaglio: se in una classe si dichiara un campo con Dim, esso viene automaticamente assunto come Private; se questo accade in una struttura, il campo viene reso Public. Prima di concludere vorrei porre l'attenzione su alcuni particolari operatori: CType e gli operatori di confronto.Module EsempioPublic Structure Frazione' Numeratore e denominatore Dim Num, DenAs Int16' Costruttore con due parametri, che inizializza Num e Den Sub New (ByVal NAs Int16,ByVal DAs Int16) Num = N Den = DEnd Sub ' Restituisce la frazione sottoforma di stringa Function Show()As String Return Num & "/" & DenEnd Function ' Semplifica la frazione Sub Semplify()Dim XAs Int16' Prende X come il valore più alto If Den > NumThen X = DenElse X = Num' E con un ciclo scova il valore più alto di X ' per cui sono divisibili sia Num che Den ' (massimo comune divisore) e li divide per quel numero If X >= 0Then ' X positivo While Not ((NumMod X = 0)And (DenMod X = 0)) X -= 1End While Else ' X negativo While Not ((NumMod X = 0)And (DenMod X = 0)) X += 1End While End If Num /= X Den /= XEnd Sub ' Somma due frazioni e restituisce la somma Shared Operator +(ByVal F1As Frazione,ByVal F2As Frazione) _As FrazioneDim F3As Frazione 'Se i denominatori sono uguali, si limita a sommare 'i numeratori If F1.Den = F2.DenThen F3.Den = F1.Den F3.Num = F1.Num + F2.NumElse ' Altrimenti esegue tutta l'operazione ' x a x*b + a*y ' - + - = --------- ' F3.Den = F1.Den * F2.Den F3.Num = F1.Num * F2.Den + F2.Num * F1.Deny b y*b End If ' F3.Semplify()Semplifica la frazione Return F3End Operator ' Sottrae due frazione e restituisce la differenza Shared Operator -(ByVal F1As Frazione,ByVal F2As Frazione) _As Frazione' F2.Num = -F2.NumSomma l'opposto del secondo membro Return F1 + F2End Operator ' Moltiplica due frazioni e restituisce il prodotto Shared Operator *(ByVal F1As Frazione,ByVal F2As Frazione) _As Frazione' Inizializza F3 con il numeratore pari al prodotto 'dei numeratori e il denominatore pari al prodotto dei 'denominatori Dim F3As Frazione =New Frazione(F1.Num * F2.Num, _ F1.Den * F2.Den) F3.Semplify()Return F3End Operator ' Divide due frazioni e restituisce il quoziente Shared Operator /(ByVal F1As Frazione,ByVal F2As Frazione) _As Frazione' Inizializza F3 eseguendo l'operazione: ' a x a y ' - / - = - * - ' b y b x Dim F3As Frazione =New Frazione(F1.Num * F2.Den, _ F1.Den * F2.Num) F3.Semplify()Return F3End Operator End Structure Sub MainDim AAs Frazione =New Frazione(2, 3)Dim BAs Frazione =New Frazione(3, 4) Console.WriteLine((A + B).Show) Console.WriteLine((A - B).Show) Console.WriteLine((A * B).Show) Console.WriteLine((A / B).Show) Console.ReadKey()End Sub End Module
CType
Come è noto, CType può
eseguire conversioni da e verso tipi conosciuti: la sua sintassi tuttavia potrebbe sviare dalla corretta dichiarazione. Infatti, nonostante
CType accetti due parametri, la sua dichiarazione ne implica uno solo, ossia il tipo che si desidera convertire, in questo caso Frazione.
Il secondo parametro è implicitamente indicato dal tipo di ritorno: se scrivessimo "CType(ByVal F As Frazione) As Double", questa
istruzione genererebbe un CType in grado di convertire dal tipo Frazione al tipo Double nella maniera consueta in cui siamo abituati:
La dichiarazione di una conversione verso Double genera automaticamente anche l'operatore CDbl, che si può usare tranquillamente al posto della versione completa di CType. Ora conviene porre l'accento sul come CType viene dichiarato: la sua sintassi non è speciale solo perchè può essere confuso da unario a binario, ma anche perchè deve dichiarare sempre se una conversione è Widening (di espansione, ossia senza perdita di dati) o Narrowing (di riduzione, con possibile perdita di dati) (per maggiori informazioni sulle conversioni, vedere capitolo 17). Per questo motivo si deve specificare una delle suddette keyword tra Shared e Operator. Ad esempio: Frazione rappresenta un numero razionale e, sebbene Double non rappresenti tutte le cifre di un possibile numero periodico, possiamo considerare che nel passaggio verso i Double non si sia perdita di dati nè di precisione in modo rilevante. Possiamo quindi definire la conversione Widening:Dim FAs Frazione '... Dim DAs Double =CType (F,Double )
Invece, la conversione verso un numero intero implica non solo una perdita di precisione rilevante ma anche di dati, quindi la definiremo Narrowing:Shared Widening Operator CType (ByVal FAs Frazione)As Double Return F.Num / F.DenEnd Operator
Shared Narrowing Operator CType (ByVal FAs Frazione)As Int32'Notare l'operatore \ di divisione intera (per maggiori 'informazioni sulla divisione intera, vedere capitolo A6) Return F.Num \ F.DenEnd Operator
Operatori di confronto
Gli operatori di confronto godono anch'essi di una caratteristica particolare: devono sempre essere definiti in coppia, < con >,
= con <>, <= con >=. Non può infatti esistere un modo per verificare se una variabile è minore di un altra e non se è
maggiore. Se manca uno degli operatori complementari, il compilatore visualizzerà un messaggio di errore.
È da notare che le espressioni come (a=b) o (a-c>b) restituiscano un valore booleano. Possono anche essere usate nelle espressioni, ma è sconsigliabile, in quanto il valore di True è spesse volte confuso: in vb.net è -1, ma a runtime è 1, mentre negli altri linguaggi è sempre 1. Queste espressioni possono tuttavia essere assegnate con sicurezza ad altri valori booleani:Shared Operator <(ByVal F1As Frazione,ByVal F2As Frazione)As Boolean 'Converte le frazioni in double e confronta questi valori Return (CType (F1,Double ) <CType (F2,Double ))End Operator Shared Operator >(ByVal F1As Frazione,ByVal F2As Frazione)As Boolean Return (CDbl (F1) >CDbl (F2))End Operator Shared Operator =(ByVal F1As Frazione,ByVal F2As Frazione)As Boolean Return (CDbl (F1) =CDbl (F2))End Operator Shared Operator <>(ByVal F1As Frazione,ByVal F2As Frazione)As Boolean 'L'operatore "diverso" restituisce sempre un valore opposto 'all'operatore "uguale" Return Not (F1 = F2)End Operator
'... a = 10 b = 20 Console.WriteLine("a è maggiore di b: " & (a > b) 'A schermo compare: "a è maggiore di b: False"
The Totem's Lair - Copyright (C) 2009
È vietata la riproduzione sia totale che parziale del sito.



