Casino online











Mercato forex






A30. Polimorfismo


Il polimorfismo è la capacità di un linguaggio ad oggetti di ridefinire i membri della classe base in modo tale che si comportino in maniera differente all'interno delle classi derivate. Questa possibilità è quindi strettamente legata all'ereditarietà. Le keywords che permettono di attuarne il funzionamento sono due, e vanno messe in coppia: Overridable e Overrides. La prima deve marcare il membro della classe base che si dovrà ridefinire, mentre la seconda contrassegna il membro della classe derivata che ne costituisce la nuova versione. È da notare che solo membri con nome uguale e signature identica (per signature s'intende la quantità e il tipo di parametri di un metodo) possono subire questo processo: ad esempio non si può ridefinire la procedura ShowText() con la proprietà Text, perchè hanno nome differente e sono di diverso tipo. La sintassi è semplice:
Class [Classe base]
    Overridable [Membro]
End Class

Class [Classe derivata]
    Inherits [Classe base]
    Overrides [Membro]
End Class 
Questo esempio prende come base la classe Person definita nel capitolo precedente e sviluppa da questa la classe Teacher (insegnante), modificandone le proprietà LastName e CompleteName:
Module Module1
    Class Person
        Protected _FirstName, _LastName As String
        Private ReadOnly _BirthDay As Date

        Public Property FirstName() As String
            Get
                Return _FirstName
            End Get
            Set(ByVal Value As String)
                If Value <> "" Then
                    _FirstName = Value
                End If
            End Set
        End Property

        'Questa proprietà sarà ridefinita nella classe Teacher 
        Public Overridable Property LastName() As String
            Get
                Return _LastName
            End Get
            Set(ByVal Value As String)
                If Value <> "" Then
                    _LastName = Value
                End If
            End Set
        End Property

        Public ReadOnly Property BirthDay() As Date
            Get
                Return _BirthDay
            End Get
        End Property

        'Questa proprietà sarà ridefinita nella classe Teacher
        Public Overridable ReadOnly Property CompleteName() As String
            Get
                Return _FirstName & " " & _LastName
            End Get
        End Property

        'Costruttore che accetta tra parametri obbligatori
        Sub New(ByVal FirstName As String, ByVal LastName As String, _
            ByVal BirthDay As Date)
            Me.FirstName = FirstName
            Me.LastName = LastName
            Me._BirthDay = BirthDay
        End Sub
    End Class

    Class Teacher
        Inherits Person
        Private _Subject As String

        Public Property Subject() As String
            Get
                Return _Subject
            End Get
            Set(ByVal Value As String)
                If Value <> "" Then
                    _Subject = Value
                End If
            End Set
        End Property

        'Ridefinisce la proprietà LastName in modo da aggiungere anche
        'il titolo di Professore al cognome
        Public Overrides Property LastName() As String
            Get
                Return "Prof. " & _LastName
            End Get
            Set(ByVal Value As String)
                'Da notare l'uso di MyBase e LastName: in questo modo si
                'richiama la vecchia versione della proprietà LastName
                'e se ne imposta il valore. Viene quindi richiamato il 
                'blocco Set vecchio: si risparmiano due righe di codice
                'poichè non si deve eseguire il controllo If su Value
                MyBase.LastName = Value
            End Set
        End Property

        'Ridefinisce la proprietà CompleteName in modo da aggiungere
        'anche la materia insegnata e il titolo di Professore
        Public Overrides ReadOnly Property CompleteName() As String
            Get
                'Anche qui viene richiamata la vecchia versione di
                'CompleteName, che restituisce semplicemente il
                'nome completo
                Return "Prof. " & MyBase.CompleteName & _
                ", dottore in " & Subject
            End Get
        End Property

        Sub New(ByVal FirstName As String, ByVal LastName As String, _
            ByVal BirthDay As Date, ByVal Subject As String)
            MyBase.New(FirstName, LastName, BirthDay)
            Me.Subject = Subject
        End Sub
    End Class

    Sub Main()
        Dim T As New Teacher("Mario", "Rossi", Date.Parse("01/01/1950"), _
        "Letteratura italiana")

        'Usiamo le nuove proprietà, ridefinite nella classe derivata
        Console.WriteLine(T.LastName)
        '> "Prof. Rossi"
        Console.WriteLine(T.CompleteName)
        '> "Prof. Mario Rossi, dottore in Letteratura italiana"

        Console.ReadKey()
    End Sub
End Module 
In questo modo si è visto come ridefinire le proprietà. Proviamo ora con un piccolo esempio sul polimorfismo dei metodi:
Class A
    Public Overridable Sub ShowText()
        Console.WriteLine("A: Testo di prova")
    End Sub
End Class

Class B
    Inherits A

    'Come si vede il metodo ha:
    '- lo stesso nome: ShowText
    '- lo stesso tipo: è una procedura
    '- gli stessi parametri: senza parametri
    'Qualunque tentativo di cambiare una di queste caratteristiche
    'produrrà un errore del compilatore, che comunica di non poter
    'ridefinire il metodo perchè non ne esistono di uguali nella
    'classe base
    Public Overrides Sub ShowText()
        Console.WriteLine("B: Testo di prova")
    End Sub
End Class 
Ultime due precisazioni: le variabili non possono subire polimorfismo, così come i membri statici.

Shadowing
Se il polimorfismo permette di ridefinire accuratamente membri che presentano le stesse caratteristiche, ed è quindi più preciso, lo shadowing permette letteralmente di oscurare qualsiasi membro che abbia lo stesso nome, indipendentemente dal tipo, dalla signature e dalla qauntità di versioni alternative presenti. Ad esempio:
Module Esempio
    Class Base
        Friend Control As Byte
    End Class

    Class Deriv
        Inherits Base
        Public Shadows Sub Control(ByVal Msg As String)
            Console.WriteLine("Control, seconda versione: " & Msg)
        End Sub
    End Class

    Sub Main()
        Dim B As New Base
        Dim D As New Deriv

        'Entrambe le classe hanno lo stesso membro di nome "Control",
        'ma nella prima è un campo friend, mentre nella seconda
        'è una procedura pubblica
        Console.WriteLine(B.Control)
        D.Control("Ciao")

        Console.ReadKey()
    End Sub
End Module 
Come si vede, la sintassi è come quella di Overrides: Shadows viene specificato tra lo specificatore di accesso (se c'e') e la tipologia del membro (in questo caso Sub, procedura). Entrambe le classi presentano Control, ma la seconda ne fa un uso totalmente diverso. Ad ogni modo l'uso dello shadowing in casi come questo è fortememente sconsigliabile: più che altro lo si usa per assicurarsi che, se mai dovesse uscire una nuova versione della classe base con dei nuovi metodi che presentano lo stesso nome di quelli della classe derivata da noi definita, non ci siano problemi di compatibilità.
Se una variabile è dichiarata Shadows, viene omessa la keyword Dim.




 

The Totem's Lair - Copyright (C) 2009
È vietata la riproduzione sia totale che parziale del sito.