Nozioni fondamentali sull'ereditarietà (Visual Basic)

L'istruzione Inherits viene usata per dichiarare una nuova classe, denominata classe derivata, basata su una classe esistente, nota come classe di base. Le classi derivate ereditano e possono estendere le proprietà, i metodi, gli eventi, i campi e le costanti definiti nella classe di base. La sezione seguente descrive alcune delle regole per l'ereditarietà e i modificatori che è possibile usare per modificare il modo in cui le classi ereditano o vengono ereditate:

  • Per impostazione predefinita, tutte le classi sono ereditabili a meno che non siano contrassegnate con la parola chiave NotInheritable. Le classi possono ereditare da altre classi del progetto o da classi in altri assembly a cui fa riferimento il progetto.

  • A differenza dei linguaggi che consentono l'ereditarietà multipla, Visual Basic consente solo l'ereditarietà singola nelle classi, di conseguenza le classi derivate possono avere una sola classe di base. Anche se l'ereditarietà multipla non è consentita nelle classi, le classi possono implementare più interfacce, raggiungendo così gli stessi risultati.

  • Per impedire l'esposizione di elementi limitati in una classe di base, il tipo di accesso di una classe derivata deve essere uguale o più restrittivo rispetto alla relativa classe di base. Ad esempio, una classe Public non può ereditare una classe Friend o Private e una classe Friend non può ereditare una classe Private.

Modificatori di ereditarietà

Visual Basic introduce le istruzioni e i modificatori a livello di classe seguenti per supportare l'ereditarietà:

  • Istruzione Inherits: specifica la classe di base.

  • Modificatore NotInheritable: impedisce ai programmatori di usare la classe come classe di base.

  • Modificatore MustInherit: specifica che la classe è destinata all'uso solo come classe di base. Le istanze delle classi MustInherit non possono essere create direttamente, ma possono essere create solo come istanze della classe di base di una classe derivata. Altri linguaggi di programmazione, ad esempio C++ e C#, usano il termine classe astratta per descrivere tale classe.

Override di proprietà e metodi nelle classi derivate

Per impostazione predefinita, una classe derivata eredita le proprietà e i metodi dalla relativa classe di base. Se una proprietà o un metodo ereditato deve comportarsi in modo diverso nella classe derivata, è possibile eseguirne l'override. Significa che è possibile definire una nuova implementazione del metodo nella classe derivata. I seguenti modificatori consentono di controllare le modalità di override di proprietà e metodi:

  • Overridable: consente di eseguire l'override di una proprietà o di un metodo in una classe derivata.

  • Overrides: esegue l'override di una proprietà o di un metodo Overridable definito nella classe di base.

  • NotOverridable: impedisce l'override di una proprietà o di un metodo in una classe che eredita. Per impostazione predefinita, i metodi Public sono NotOverridable.

  • MustOverride: richiede che una classe derivata esegua l'override della proprietà o del metodo. Quando viene usata la parola chiave MustOverride, la definizione del metodo è costituita solo dall'istruzione Sub, Function o Property. Non sono consentite altre istruzioni e in particolare non è presente alcuna istruzione End Sub o End Function. I metodi MustOverride devono essere dichiarati nelle classi MustInherit.

Si supponga di voler definire le classi per gestire le retribuzioni. È possibile definire una classe Payroll generica che contiene un metodo RunPayroll che calcola la retribuzione per una settimana tipica. È quindi possibile usare Payroll come classe di base per una classe BonusPayroll più specializzata, che può essere usata per la distribuzione dei bonus dei dipendenti.

La classe BonusPayroll può ereditare ed eseguire l'override del metodo PayEmployee definito nella classe Payroll di base.

Nell'esempio seguente viene definita una classe di base, Payroll,, e una classe derivata, BonusPayroll, che esegue l'override di un metodo ereditato, PayEmployee. Una routine, RunPayroll, crea e quindi passa un oggetto Payroll e un oggetto BonusPayroll a una funzione, Pay, che esegue il metodo PayEmployee di entrambi gli oggetti.

Const BonusRate As Decimal = 1.45D
Const PayRate As Decimal = 14.75D

Class Payroll
    Overridable Function PayEmployee(
        ByVal HoursWorked As Decimal,
        ByVal PayRate As Decimal) As Decimal

        PayEmployee = HoursWorked * PayRate
    End Function
End Class

Class BonusPayroll
    Inherits Payroll
    Overrides Function PayEmployee(
        ByVal HoursWorked As Decimal,
        ByVal PayRate As Decimal) As Decimal

        ' The following code calls the original method in the base 
        ' class, and then modifies the returned value.
        PayEmployee = MyBase.PayEmployee(HoursWorked, PayRate) * BonusRate
    End Function
End Class

Sub RunPayroll()
    Dim PayrollItem As Payroll = New Payroll
    Dim BonusPayrollItem As New BonusPayroll
    Dim HoursWorked As Decimal = 40

    MsgBox("Normal pay is: " &
        PayrollItem.PayEmployee(HoursWorked, PayRate))
    MsgBox("Pay with bonus is: " &
        BonusPayrollItem.PayEmployee(HoursWorked, PayRate))
End Sub

Parola chiave MyBase

La parola chiave MyBase si comporta come una variabile oggetto che fa riferimento alla classe di base dell'istanza corrente di una classe. MyBase viene comunemente usata per accedere ai membri della classe di base sottoposti a override o nascosti in una classe derivata. In particolare, la parola chiave MyBase.New viene usata per chiamare in modo esplicito un costruttore della classe di base da un costruttore di classi derivate.

Si supponga, ad esempio, di progettare una classe derivata che esegue l'override di un metodo ereditato dalla classe di base. Il metodo sottoposto a override può chiamare il metodo nella classe dii base e modificare il valore restituito come illustrato nel frammento di codice seguente:

Class DerivedClass
    Inherits BaseClass
    Public Overrides Function CalculateShipping(
        ByVal Dist As Double,
        ByVal Rate As Double) As Double

        ' Call the method in the base class and modify the return value.
        Return MyBase.CalculateShipping(Dist, Rate) * 2
    End Function
End Class

L'elenco seguente descrive le restrizioni relative all'uso di MyBase:

  • MyBase fa riferimento alla classe di base immediata e ai relativi membri ereditati. Non può essere usata per accedere ai membri Private nella classe.

  • MyBase è una parola chiave, non un oggetto reale. MyBase non può essere assegnata a una variabile, passata alle routine o usata in un confronto Is.

  • Il metodo che MyBase qualifica non deve essere definito nella classe di base immediata e può essere invece definito in una classe di base ereditata indirettamente. Per la corretta compilazione di un riferimento qualificato da MyBase, alcune classi di base devono contenere un metodo che corrisponde al nome e ai tipi dei parametri visualizzati nella chiamata.

  • Non è possibile usare MyBase per chiamare i metodi della classe di base MustOverride.

  • La parola chiave MyBase non può essere usata per qualificare se stessa. Di conseguenza, il codice seguente non è valido:

    MyBase.MyBase.BtnOK_Click()

  • La parola chiave MyBase non può essere usata nei moduli.

  • La parola chiave MyBase non può essere usata per accedere ai membri della classe di base contrassegnati come Friend se la classe di base si trova in un assembly diverso.

Per altre informazioni e un altro esempio, vedere Procedura: accedere a una variabile nascosta da una classe derivata.

Parola chiave MyClass

La parola chiave MyClass si comporta come una variabile oggetto che fa riferimento all'istanza corrente di una classe come implementata in origine. MyClass è simile a Me, ma ogni chiamata a metodo e proprietà su MyClass viene considerata come se il metodo o la proprietà fossero NotOverridable. Di conseguenza, il metodo o la proprietà non sono interessati dall'override in una classe derivata.

  • MyClass è una parola chiave, non un oggetto reale. MyClass non può essere assegnata a una variabile, passata alle routine o usata in un confronto Is.

  • MyClass fa riferimento alla classe contenitore e ai relativi membri ereditati.

  • La parola chiave MyClass può essere usata come qualificatore per i membri Shared.

  • MyClass non può essere usata all'interno di un metodo Shared, ma può essere usata all'interno di un metodo di istanza per accedere a un membro condiviso di una classe.

  • MyClass non può essere usata nei moduli standard.

  • MyClass può essere usata per qualificare un metodo definito in una classe di base e che non ha un'implementazione del metodo fornito in tale classe. Un riferimento di questo tipo ha lo stesso significato di MyBase.Method.

Nell'esempio seguente vengono confrontati Me e MyClass.

Class baseClass
    Public Overridable Sub testMethod()
        MsgBox("Base class string")
    End Sub
    Public Sub useMe()
        ' The following call uses the calling class's method, even if
        ' that method is an override.
        Me.testMethod()
    End Sub
    Public Sub useMyClass()
        ' The following call uses this instance's method and not any
        ' override.
        MyClass.testMethod()
    End Sub
End Class
Class derivedClass : Inherits baseClass
    Public Overrides Sub testMethod()
        MsgBox("Derived class string")
    End Sub
End Class
Class testClasses
    Sub startHere()
        Dim testObj As derivedClass = New derivedClass()
        ' The following call displays "Derived class string".
        testObj.useMe()
        ' The following call displays "Base class string".
        testObj.useMyClass()
    End Sub
End Class

Anche se derivedClass esegue l'override di testMethod, la parola chiave MyClass in useMyClass annulla gli effetti dell'override e il compilatore risolve la chiamata alla versione della classe di base di testMethod.

Vedi anche