Inleiding
In het vorige artikel VB4VO is ingegaan op de basiselementen van Visual Basic en het DotNet raamwerk. In dit artikel gaan we in op een interessanter onderdeel: de manier waarop objectoriëntatie geïmplementeerd is in Visual Basic. Persoonlijk heb ik Visual Objects altijd enorm gewaardeerd vanwege de wijze waarop objectoriëntatie is toegepast. Inkapseling en overerving waren elegant opgezet en boden de mogelijkheid om een goed objectmodel te introduceren. Allerlei design patterns zoals beschreven door Erich Gamma zijn reeds toegepast lang voordat deze beschreven waren (denk bijvoorbeeld aan manier van notification tussen dbservers en datawindows wat een observer pattern is).
Toch is de manier waarop objectoriëntatie toegepast wordt in DotNet, duidelijk een volgende generatie van dit paradigma. Alle elementen die we al kennen uit de VO objectoriëntatie zijn voorhanden, maar er is meer. In dit artikel wil ik de belangrijkste elementen van de DotNet opzet beschrijven. Er is een eenvoudige voorbeeldapplicatie opgenomen die een op zich weinig relevant objectmodel toont, maar waarin wel de concepten van objectoriëntatie goed naar voren komen.
Basics
In het onderstaande codevoorbeeld is te zien met welke syntax een object wordt gedefinieerd in Visual Basic.
Public Class Persoon
Protected VoorNaam As String
Protected AchterNaam As String
Private GeboorteDatum As Date
Public Sub New(ByVal voornaam As String, ByVal achternaam As String)
Me.AchterNaam = achternaam
Me.VoorNaam = voornaam
End Sub
Sub New(ByVal achternaam As String)
Me.AchterNaam = achternaam
Me.VoorNaam = "Onbekend"
End Sub
Property VolledigeNaam()
Get
Return Me.VoorNaam & " " & Me.AchterNaam
End Get
Set(ByVal Value)
Dim myArray() As String = Split(Value)
Me.VoorNaam = myArray(1)
Me.AchterNaam = myArray(2)
End Set
End Property
Sub SetGeboorteDatum(ByVal gebdat As Date)
Me.GeboorteDatum = gebdat
End Sub
Overrides Function ToString() As String
Return Me.VoorNaam & " " & Me.AchterNaam & _
" is geboren op " & _
Me.GeboorteDatum.ToString("D")
End Function
End Class
Het voorbeeld toont hoe een klasse gedefinieerd wordt door de tags “class” en “end class”. Daarbinnen is het mogelijk om eigenschappen, methoden en property get/sets te definiëren. Eigenschappen kunnen net als in VO een scope hebben. De belangrijkste zijn public, protected en private. Voor public en protected is de analogie met VO duidelijk, private is vergelijkbaar met Hidden in VO.
Init methoden worden in VB weergegeven met New. In de code is een duidelijke wijziging te zien ten opzichte van VO, namelijk dat er meerdere methoden gedefinieerd kunnen worden met dezelfde naam, maar met verschillende parameters. Dit wordt method of function overloading genoemd. Het idee hierachter is dat je door deze opzet toch altijd met strong typed methoden kunt werken. Je kunt dus altijd de compiler een groot aantal controles laten doen die je behulpzaam zijn bij het maken van stabiele code. Daarnaast hoeven niet meer allerlei controles opgenomen te worden in het begin van een methode wat het type van een parameter nu eigenlijk is.
Accesses en Assigns zijn elementen die in VB zijn vervangen door Property Set’s en Get’s. De werkwijze is hetzelfde. Je maakt een stukje logica om een eigenschap heen die ervoor zorgt dat je eigenschappen gevalideerd of omgezet worden. De Property Set van VolledigeNaam is daar een aardig voorbeeld van.
Methoden uit VO worden in VB vervangen door Functions en Subs. Een Function heeft een returnwaarde en een Sub niet. Daarnaast kun je aan Functions en Subs een aantal nieuwe tags toevoegen waarvan Overrides een voorbeeld is. ToString is bijvoorbeeld een Function die in elk object van VB voorkomt. Met ToString wordt een object naar een string ‘vertaald’. Overrides zorgt ervoor dat deze Function zoals die voorkomt in het object waarvan het huidige object afstamt, wordt vervangen door de hier opgegeven versie.
Interfaces
Een onbekend fenomeen in VO is het interface. Met een interface kun je definiëren aan welke voorwaarden een aantal functies binnen een klasse moet voldoen. Als een klasse een interface implementeert, dan moeten de methoden zoals gedefinieerd in het interface zo geïmplementeerd worden. Ook hier geldt weer dat de compiler deze controles voor je uitvoert, met als gevolg stabielere code. Een voorbeeld:
Public Interface IFunctie
Function GetFunctie() As String
End Interface
In de naamgevingsconventie van VB begint een interface altijd met een I. Het is handig deze conventie te volgen, omdat dit de code leesbaarder maakt. De sessie van Mark Vroom op de website geeft een goed beeld van hoe de naamgevingsconventie van VB is opgezet.
Met een interface kun je definiëren aan welke voorwaarden een aantal functies binnen een klasse moet voldoen
OO Uitbreidingen
In VB is een aantal OO uitbreidingen voorhanden die het leven van de ontwikkelaar aangenamer maken. Ook hier weer een stukje voorbeeldcode om een en ander te verduidelijken.
Public Class Medewerker
Inherits Persoon
Implements IFunctie
Protected strFunctie As String
Public Shared AantalCollegas As Int32
Sub New(ByVal voornaam As String, ByVal achternaam As String, _
ByVal functie As String)
MyBase.New(voornaam, achternaam)
Me.strFunctie = functie
End Sub
Public Function GetFunctie() As String Implements IFunctie.GetFunctie
GetFunctie = Me.strFunctie
End Function
Overrides Function ToString() As String
Return Me.VolledigeNaam & " Heeft de functie van " & Me.strFunctie
End Function
Function Collegas() As Int32
Return Me.AantalCollegas
End Function
End Class
Allereerst is te zien hoe de klasse Medewerker overerft van Persoon en de interface Ifunctie implementeert. Binnen VB is meervoudige overerving niet mogelijk; wel kun je meerdere interfaces implementeren.
Binnen VB is meervoudige overerving niet mogelijk; wel kun je meerdere interfaces implementeren
Verder is te zien hoe de constructor van de medewerker klasse de constructor van de Persoon klasse uitbreidt. De MyBase tag komt overeen met Super in VO.
Een aardige uitbreiding is de shared tag. Hiermee kun je op klasseniveau eigenschappen en methoden definiëren. In de voorbeeldtoepassing is de volgende implementatie opgenomen van de shared eigenschap AantalCollegas.
Private Sub ButtonCollegas_Click(_
ByVal sender As System.Object,_
ByVal e As System.EventArgs) Handles ButtonCollegas.Click
Dim objMedewerker1 As New _
Medewerker("Inge", "Gevers", "Softwareontwikkelaar")
Dim objMedewerker2 As New Medewerker("Piet", "Dijkstra", "Tester")
objMedewerker1.AantalCollegas = 5
objMedewerker1.AantalCollegas = 10
Me.TextBoxResult.Text = Convert.ToString(objMedewerker1.Collegas())
End Sub
Je zou in dit voorbeeld verwachten dat in de tekstbox de waarde 5 komt te staan, maar dat is niet het geval: de waarde 10 wordt zichtbaar. Het idee erachter is dat de waarde niet op object (instantie) maar op klasse niveau wordt geregistreerd.
Zo is er een aantal klassen gedefinieerd in het DotNet raamwerk met vrijwel alleen maar shared fuinctions. Denk bijvoorbeeld aan de namespace System.Math die voornamelijk uit shared functions voor rekenkundige bewerkingen bestaat. Bijkomend voordeel is dat deze klasse niet eerst geïnstantieerd hoeft te worden. Een toepassing is te zien in het bovenstaande voorbeeld waarbij de Convert klasse wordt aangeroepen en niet een object van het type Convert.
Conclusie
In VB.NET is een aantal elementen opgenomen op het vlak van objectoriëntatie die het leven van de softwareontwikkelaar een stuk aangenamer maken. Met name de method overloading, Interfaces en shared elementen van een klasse zijn hier mooie voorbeelden van. De controle van de programmacode kan worden gedelegeerd aan de compiler, en wie delegeert er niet graag een saaie controletaak naar de PC waarachter hij werkt?
Tot slot staat in de help van het framework een goede beschrijving van de mogelijkheden van objectoriëntatie in het framework. Ik hoop in ieder geval dat met dit artikel jullie interesse in de OO-opzet van DotNet gewekt is.
Download de sample code