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 classeFriend
oPrivate
e una classeFriend
non può ereditare una classePrivate
.
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 classiMustInherit
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 metodoOverridable
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 metodiPublic
sonoNotOverridable
.MustOverride
: richiede che una classe derivata esegua l'override della proprietà o del metodo. Quando viene usata la parola chiaveMustOverride
, la definizione del metodo è costituita solo dall'istruzioneSub
,Function
oProperty
. Non sono consentite altre istruzioni e in particolare non è presente alcuna istruzioneEnd Sub
oEnd Function
. I metodiMustOverride
devono essere dichiarati nelle classiMustInherit
.
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 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 membriPrivate
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 confrontoIs
.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 daMyBase
, 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 baseMustOverride
.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 comeFriend
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 confrontoIs
.MyClass
fa riferimento alla classe contenitore e ai relativi membri ereditati.La parola chiave
MyClass
può essere usata come qualificatore per i membriShared
.MyClass
non può essere usata all'interno di un metodoShared
, 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 diMyBase.
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
.