Casino online











Mercato forex






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:
Shared Operator [simbolo dell'operatore]([parametri]) As [tipo]
  'Codice dell'operatore
End Operator 
È 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:
Module Esempio
    Public Structure Frazione
        'Numeratore e denominatore
        Dim Num, Den As Int16
        'Costruttore con due parametri, che inizializza Num e Den
        Sub New(ByVal N As Int16, ByVal D As Int16)
            Num = N
            Den = D
        End Sub
        
        'Restituisce la frazione sottoforma di stringa
        Function Show() As String
            Return Num & "/" & Den
        End Function
        
        'Semplifica la frazione
        Sub Semplify()
            Dim X As Int16
            'Prende X come il valore più alto
            If Den > Num Then X = Den Else 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 >= 0 Then
                'X positivo
                While Not ((Num Mod X = 0) And (Den Mod X = 0))
                    X -= 1
                End While
            Else
                'X negativo
                While Not ((Num Mod X = 0) And (Den Mod X = 0))
                    X += 1
                End While
            End If
            Num /= X
            Den /= X
        End Sub
        
        'Somma due frazioni e restituisce la somma
        Shared Operator +(ByVal F1 As Frazione, ByVal F2 As Frazione) _
            As Frazione
            Dim F3 As Frazione

            'Se i denominatori sono uguali, si limita a sommare 
            'i numeratori
            If F1.Den = F2.Den Then
                F3.Den = F1.Den
                F3.Num = F1.Num + F2.Num
            Else
                'Altrimenti esegue tutta l'operazione
                'x   a   x*b + a*y
                '- + - = ---------
                'y   b      y*b
                F3.Den = F1.Den * F2.Den
                F3.Num = F1.Num * F2.Den + F2.Num * F1.Den
            End If

            'Semplifica la frazione
            F3.Semplify()
            Return F3
        End Operator
        
        'Sottrae due frazione e restituisce la differenza
        Shared Operator -(ByVal F1 As Frazione, ByVal F2 As Frazione) _
            As Frazione
            'Somma l'opposto del secondo membro
            F2.Num = -F2.Num
            Return F1 + F2
        End Operator
        
        'Moltiplica due frazioni e restituisce il prodotto
        Shared Operator *(ByVal F1 As Frazione, ByVal F2 As Frazione) _
            As Frazione
         'Inizializza F3 con il numeratore pari al prodotto 
            'dei numeratori e il denominatore pari al prodotto dei 
            'denominatori
            Dim F3 As Frazione = New Frazione(F1.Num * F2.Num, _
                F1.Den * F2.Den)
            F3.Semplify()
            Return F3
        End Operator
        
        'Divide due frazioni e restituisce il quoziente
        Shared Operator /(ByVal F1 As Frazione, ByVal F2 As Frazione) _
            As Frazione
            'Inizializza F3 eseguendo l'operazione:
            'a   x   a   y
            '- / - = - * -
            'b   y   b   x
            Dim F3 As Frazione = New Frazione(F1.Num * F2.Den, _
                F1.Den * F2.Num)
            F3.Semplify()
            Return F3
        End Operator
    End Structure
    
    Sub Main
        Dim A As Frazione = New Frazione(2, 3)
        Dim B As 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 
È 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.


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:
Dim F As Frazione
'...
Dim D As Double = CType(F, Double) 
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:
Shared Widening Operator CType(ByVal F As Frazione) As Double
    Return F.Num / F.Den
End Operator 
Invece, la conversione verso un numero intero implica non solo una perdita di precisione rilevante ma anche di dati, quindi la definiremo Narrowing:
Shared Narrowing Operator CType(ByVal F As Frazione) As Int32
    'Notare l'operatore \ di divisione intera (per maggiori 
    'informazioni sulla divisione intera, vedere capitolo A6)
    Return F.Num \ F.Den
End 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.
Shared Operator <(ByVal F1 As Frazione, ByVal F2 As Frazione) As Boolean
    'Converte le frazioni in double e confronta questi valori
    Return (CType(F1, Double) < CType(F2, Double))
End Operator

Shared Operator >(ByVal F1 As Frazione, ByVal F2 As Frazione) As Boolean
    Return (CDbl(F1) > CDbl(F2))
End Operator

Shared Operator =(ByVal F1 As Frazione, ByVal F2 As Frazione) As Boolean
    Return (CDbl(F1) = CDbl(F2))
End Operator

Shared Operator <>(ByVal F1 As Frazione, ByVal F2 As Frazione) As Boolean
    'L'operatore "diverso" restituisce sempre un valore opposto
    'all'operatore "uguale"
    Return Not (F1 = F2)
End Operator 
È 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:
'...
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.