C# onder de loep
In C# is het mogelijk om een methode Virtual of Abstract te maken. Wat beide keywords gemeen hebben, is dat ze te maken hebben met overerving. En het verschil? Laten we beide keywords eens nader beschouwen.
Virtual
Het doel van een virtuele methode is om aan te geven dat de implementatie van een methode overschreven KAN worden door een class die erft van de klasse die de virtuele methode definieert. De klasse die de functie definieert levert zelf echter al wel een implementatie voor de functie.
Voorbeeld:
public class EersteClass
{
public virtual string GetVirtualName()
{
return "EersteClass - Virtual";
}
}
public class TweedeClass : EersteClass
{
public override string GetVirtualName()
{
return "TweedeClass - Override";
}
}
De tweede klasse erft van de eerste.
Door nu onder een button de volgende code aan te roepen kunnen we het gedrag van de klassen bekijken.
private void button1_Click(object sender, System.EventArgs e)
{
EersteClass ec = new TweedeClass();
TweedeClass tc = new TweedeClass();
MessageBox.Show( ec.GetVirtualName() ) ;
MessageBox.Show( tc.GetVirtualName() ) ;
ec = new EersteClass();
MessageBox.Show( ec.GetVirtualName() ) ;
}
Nog even een opmerking over het keyword "override". Dit keyword lijkt in eerste instantie niet noodzakelijk, maar probeer het in de bovenstaande voorbeeld in TweedeClass het keyword maar eens weg te laten en run de test dan nog eens. Je zult zien, dat het gedrag ineens heel anders is. Op het moment dat je een object van het type TweedeClass cast naar EersteClass, vervalt het gedrag van de methode GetVirtualName() naar de implementatie van EersteClass. Dit is gedrag dat je slechts in zeer uitzonderlijke gevallen zult willen hebben.
Vergeet dus niet het keyword "override" te gebruiken.
Voor mensen die uit de Java hoek komen: in Java hoef je niet aan te geven dat een methode virtual is. Bij C# moet dat dus wel. Het idee is dat de programmeur op deze manier kan aangeven of hij inheritance wil toestaan of niet.
Abstract
Het doel van een abstracte methode is aan te geven dat een klasse die erft van deze klasse de functie MOET implementeren. De klasse zelf levert geen implementatie, alleen een prototype van hoe de functie eruit moet zien. Sterker nog, in C# is het zo dat als een klasse een abstracte methode heeft, de hele klasse abstract is. Van een abstracte klasse kun je geen object instantiëren.
Voorbeeld:
public abstract class EersteClass
{
public abstract string GetAbstractName();
}
public class TweedeClass : EersteClass
{
public override string GetAbstractName();
{
return "TweedeClass - Override";
}
}
Bij de eerste klasse kunnen we niet eens een implementatie geven van de functie GetAbstractName(). Doen we dat wel, dan geeft de compiler een error. Met de volgende code kun je zien wat het gedrag is.
private void button1_Click(object sender,
System.EventArgs e)
{
EersteClass ec = new TweedeClass();
TweedeClass tc = new TweedeClass();
MessageBox.Show( ec.GetVirtualName() ) ;
MessageBox.Show( tc.GetVirtualName() ) ;
ec = new EersteClass();
MessageBox.Show( ec.GetVirtualName() ) ;
}
De compiler zal een foutmelding geven op "ec = new EersteClass();". Het is niet toegestaan om een instantie van een abstracte klasse te maken. Hiermee wordt de programmeur gedwongen om eerst een TweedeClass te implementeren.
Haal de laatste twee regels even weg en probeer het dan nog een keer.
private void button1_Click(object sender, System.EventArgs e)
{
EersteClass ec = new TweedeClass();
TweedeClass tc = new TweedeClass();
MessageBox.Show( ec.GetVirtualName() ) ;
MessageBox.Show( tc.GetVirtualName() ) ;
}
Nu werkt het voorbeeld wel en zoals je ziet, wordt in beide gevallen de methode van TweedeClass aangeroepen.
Conclusie
Gebruik virtual voor methodes waarvan de implementatie misschien nog aangepast moeten worden in ervende klassen en gebruik abstract als de ervende klasse verplicht is een implementatie te leveren.
Overridable of MustOverride?
VB.NET onder de loep
In VB.NET is het mogelijk om een methode Overridable of MustOverride te maken. Wat beide keywords gemeen hebben is dat ze te maken hebben met overerving. En het verschil? Laten we beide keywords eens nader beschouwen…
Overridable
Het doel van een overridable methode is om aan te geven dat de implementatie van een methode overschreven KAN worden door een class die erft van de klasse die de overridable methode definieert. De klasse die de functie definieert, levert zelf echter al wel een implementatie voor de functie.
Voorbeeld:
Public Class EersteClass
Public Overridable Function GetOverridableText()_
As String
Return “EerstClass - Overridable”
End Function
End Class
Public Class TweedeClass
Inherits EersteClass
Public Overrides Function GetOverridableText () _
As String
Return “TweedeClass – Overrides”
End Function
End Class
De tweede klasse erft van de eerste.
Door nu onder een button de volgende code aan te roepen kunnen we het gedrag van de klassen bekijken.
Private Sub Button1_Click(
ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles Button1.Click
Dim ec As EersteClass = new TweedeClass
Dim tc As TweedeClass = new TweedeClass
MessageBox.Show(ec.GetOverridableText)
MessageBox.Show(tc.GetOverridableText)
ec = new EersteClass
MessageBox.Show(ec.GetOverridableText)
End Sub
Nog even een opmerking over het keyword "overrides". Dit keyword lijkt in eerste instantie niet noodzakelijk, maar probeer in het bovenstaande voorbeeld in TweedeClass het keyword maar eens weg te laten en run de test dan nog eens. Je zult zien dat het gedrag ineens heel anders is. Op het moment dat je een object van het type TweedeClass cast naar EersteClass vervalt het gedrag van de methode GetOverridableText() naar de implementatie van EersteClass. Dit is gedrag dat je slechts in zeer uitzonderlijke gevallen zult willen hebben.
Vergeet dus niet het keyword "overrides" te gebruiken.
MustOverride
Het doel van een MustOverride methode is om aan te geven dat een klasse die erft van deze klasse de functie MOET implementeren. De klasse zelf levert geen implementatie, alleen een prototype van hoe de functie eruit moet zien. Sterker nog, in VB.NET is het zo dat als een klasse een MustOverride methode heeft, de hele klasse gemarkeerd moet worden als MustInherit. Met andere woorden, je moet erven van deze klasse, want je kunt van deze klasses geen object instantiëren.
Voorbeeld:
Public MustInherit Class EersteClass
Public MustOverride Function GetMustOverrideText() _
As String
Public Class TweedeClass
Inherits EersteClass
Public Overrides Function GetMustOverrideText() As _
String
End Function
End Class
Bij de eerste klasse kunnen we niet eens een implementatie geven van de functie GetMustOverrideText(). Doen we dat wel, dan geeft de compiler een error. Met de volgende code kun je zien wat het gedrag is.
Private Sub Button1_Click(
ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles Button1.Click
Dim ec As EersteClass = new TweedeClass
Dim tc As TweedeClass = new TweedeClass
MessageBox.Show(ec.MustOverrideText)
MessageBox.Show(tc.MustOverrideText)
ec = new EersteClass
MessageBox.Show(ec.MustOverrideText)
End Sub
De compiler zal een foutmelding geven op "ec = new EersteClass".
Het is niet toegestaan om een instantie van een MustInherit klasse te maken. Hiermee wordt de programmeur gedwongen om eerst een TweedeClass te implementeren.
Haal de laatste twee regels weg en probeer het dan nog een keer.
Private Sub Button1_Click(
ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles Button1.Click
Dim ec As EersteClass = new TweedeClass
Dim tc As TweedeClass = new TweedeClass
MessageBox.Show(ec.MustOverrideText)
MessageBox.Show(tc.MustOverrideText)
End Sub
Nu werkt het voorbeeld wel en zoals je ziet wordt in beide gevallen de methode van TweedeClass aangeroepen.
Conclusie
Gebruik Overridable voor methodes waarvan de implementatie misschien nog aangepast moeten worden in ervende klassen en gebruik MustOverride als de ervende klasse verplicht is een implementatie te leveren.