Visual Basic 2012 Voorbeelden
   

visual basic 2012 broncode voorbeelden

Blijf op de hoogte van de recente aanpassingen op vbvoorbeelden!

Microsoft Visual Studio 2012Microsoft Developers Network - Visual BasicMicrosoft .NET Framework

9.13. Constructoren - New

Print Email Deel op Twitter Deel op Facebook

Dit artikel is gepubliceerd op maandag 15 oktober 2012 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.

In de client tot nu toe hebben we bijna steeds meteen na het instantiëren van een object eigenschapswaarden ingesteld voor dat object.  Dit is vrij logisch, want met een "leeg" object zijn we immers meestal niet veel.  Met "leeg" wordt hier bedoeld : zonder object-specifieke toestand, zonder specifieke waarden (andere dan de initiële) voor die instantie.

Om af te dwingen dat bij het aanmaken van een instantie voor bepaalde eigenschappen van deze instantie initiële waardes worden voorzien kan men gebruik maken van constructoren.
Dit zijn steeds procedures met de identifier New.  Deze constructoren worden impliciet aangeroepen bij het gebruik van een object initializer (keyword New gevolgd door de identifier van de klasse die men wil instantiëren).

Men kan in de constructor argumentvariabelen definiëren, waardoor het mogelijk wordt bij het instantiëren (in de objectinitializer) de nodige argumentwaarden door te geven.

Hieronder een voorbeeld van een klasse Person met een constructor (1) die toelaat een initiële Name-eigenschapswaarde op te geven in de object initializer.
Visual Basic 2012 Broncode - Codevoorbeeld 270
Class Person
    Public Sub New(ByVal name As String)                                   ' (1)
        Me.Name = name
    End Sub
    Public Property Name As String
End Class
Module Client1
    Sub Main()
        Dim person1 As Person = New Person("John")                         ' (2)
        Console.WriteLine(person1.Name)
        '
        Console.ReadLine()
    End Sub
End Module
Console Application Output
John
De client MOET hier (2) nu meteen bij het construeren van het object (van het type Person) een initiële Name waarde opgeven.  De doorgegeven argumentwaarde (name) wordt vervolgens toegekend aan de eigenschap ( Me.Name).
Dit vereenvoudigd natuurlijk sterk de client-code.

Ook clients (of clientprogrammeurs) kunnen de naam van argumentvariabelen zien.  Bedenk maar hoe bijvoorbeeld in de Visual Studio IDE er een "tooltip" komt met informatie over de verwachte te doorgegeven argumentwaarden als je een method aanroept.  In deze informatie staat ook de identifier van de argumentvariabelen vermeldt.  Een clientprogrammeur kan steeds de naam van de argumentvariabelen zien.
Dit heeft als gevolg dat we er best voor opteren om zo duidelijk mogelijke identifiers uit te kiezen voor deze argumentvariabelen.  Liefst een naam die de rol van de doorgegeven argumentwaarde weerspiegelt.

Gezien het in bovenstaand voorbeeld gaat om een initiële waarde voor een property die ook beschikbaar is voor clients, ligt de keuze voor de identifier van de gerelateerde argumentvariabele voor de hand.  Namelijk dezelfde identifier als die voor de gerelateerde property (Name property en name argumentvariabele).

Om het voor de compiler duidelijk te houden dat de argumentwaarde moet toegekend worden aan de property (en niet opnieuw aan de argumentvariabele zelf) verwijzen we naar deze property door er de objectexpressie Me voor te plaatsen.
Keyword Me is steeds een verwijzing naar het object dat op dat moment in uitvoering is.  Men kan naar eender welke instancemember verwijzen binnen een klasse door voor de identifier van die member Me. te plaatsen, dit is niet noodzakelijk, maar kan eventueel verduidelijken dat het om een aanroep naar een instancemember gaat.  Me is enkel noodzakelijk om mogelijke verwarring te vermijden voor de compiler bij het verwijzen een member van het object ( dat op dat moment in uitvoering is) wanneer een andere member of variabele dezelfde identifier zou gebruiken.

Constructoren worden niet alleen gebruikt voor het instellen van initiële waarden voor eigenschappen.  Eender wat moet gebeuren bij het construeren van een object kan men in de constructor coderen.

9.13.1. Default Constructor en MyBase

Wat niet opvalt (omdat het achter de schermen wordt toegevoegd) is dat elke klasse die je definieert een constructor heeft.  Definieer je dus zelf niet expliciet een constructor in een klasse dan wordt er achter de schermen - wat men noemt - een default constructor toegevoegd.

Deze default constructor ziet er steeds als volgt uit :
Public Sub New()
    MyBase.New()
End Sub
Het gaat dus om een publiek beschikbare constructor (access modifier Public).  Deze dient publiek beschikbaar te zijn, anders kan men geen object instantiëren van dit type.

Onderstaande klasse bijvoorbeeld heeft een constructor die ingekapseld is.
Visual Basic 2012 Broncode - Codevoorbeeld 271
Class SomeClass
    Private Sub New()
        MyBase.New()
    End Sub
End Class
Module Client2
    Sub Main()
        'Dim object1 As SomeClass = New SomeClass  ' impossible
    End Sub
End Module
Clients hebben hier dus niet de mogelijkheid om een object van dit type te construeren.  Het inkapselen van constructoren kan bijvoorbeeld nuttig zijn om het "singleton pattern" te implementeren, hierover later meer.

Uit bovenstaand voorbeeld is ook duidelijk geworden dat indien men zelf expliciet een constructor definieert in een klasse, er geen sprake meer is van de default constructor.  Deze wordt dus enkel toegevoegd indien er nog geen aanwezig zou zijn.
Voegt men dus bijvoorbeeld een constructor met argumenten toe aan een klasse, dan is men verplicht argumentwaarden op te geven in een object initializer voor het instantiëren van een object van dat type. (althans wanneer er geen extra argumentloze constructor aanwezig zou zijn)

De default constructor is uiteraard argumentenloos.  Het systeem dat achter de schermen deze constructor toevoegt heeft immers geen idee welke parameters van nut zouden kunnen zijn.  En bijkomend ook geen idee van hebben wat aan te vangen met de doorgegeven argumentwaarden.

Op de eerste implementatieregel van deze default constructor staat steeds een aanroep naar de parameterloze constructor van de basisklasse.  We weten ondertussen dat iedere klasse die we definiëren een afgeleide klasse is.
Geven we niet zelf op van welk type onze klasse overerft, dan wordt automatisch overgeërfd van het type System.Object.

Het MyBase keyword is vergelijkbaar met Me, maar kan gebruikt worden om naar members te verwijzen die in de basisklasse zijn gedefinieerd.  Dit kan gaan over overgeërfde members of over constructoren van de basisklasse.
Constructoren worden immers nooit overgeërfd in Visual Basic, dus een aanroep naar die constructor gedefinieerd in die basisklasse kan enkel aan de hand van het MyBase keyword.

Een verschil tussen Me en MyBase is dat Me een objectexpressie is, in tegenstelling tot MyBase.
Een constructie als volgende is bijgevolg NIET mogelijk :
With MyBase
    ...
End With
Onthoud dus dat bij het construeren van een object steeds alle constructoren van de basisklassen worden uitgevoerd.
Bemerk wel dat het by default gaat om een aanroep naar de parameterloze constructor van de basisklasse.  Men zal deze default-aanroep moeten vervangen (door een expliciete call) naar een niet parameterloze constructor indien de basisklasse niet over een dergelijke parameterloze constructor beschikt.
Zoals ook in onderstaand voorbeeld wordt verduidelijkt.
Visual Basic 2012 Broncode - Codevoorbeeld 272
Class Student : Inherits Person
    Public Sub New(ByVal name As String, ByVal classGroup As String)
        MyBase.New(name)
        Me.ClassGroup = classGroup
    End Sub
    Public Property ClassGroup As String
End Class
Module Client3
    Sub Main()
        Dim student1 As Student = New Student("John", "Group 1")
        With student1
            Console.WriteLine(.Name)
            Console.WriteLine(.ClassGroup)
        End With
        '
        Console.ReadLine()
    End Sub
End Module
Console Application Output
John
Group 1
Hier beschikt de klasse Student enkel over een constructor die twee argumentwaarden verwacht (de default constructor is immers vervangen door de expliciet gedefinieerde constructor).  Dus moet in de client van het type Student in de object initializer ook argumentwaarden voor die argumenten worden opgegeven.

De basisklasse Person beschikt niet over een parameterloze constructor, dus zijn we verplicht een constructor op te nemen in het afgeleide type Student, waarin we dan nog eens verplicht zijn de niet parameterloze constructor van die basisklasse Person aan te roepen (waarbij we dus de nodige argumentwaarden moeten doorgeven).

Vaak komt dit handig uit, zo ook in dit voorbeeld, die initialisatiecode die hier de Name eigenschap op een initiële waarde zet, kan zo worden herbruikt, en hoeft niet te worden geherimplementeerd in de constructor van de afgeleide klasse Student.

De aanroep naar de constructor van de basisklasse moet steeds op de eerste regel gebeuren van de constructor van de afgeleide klasse.

Indien er wel een parameterloze constructor in basisklasse was geweest, hadden we niet expliciet een MyBase.New()-call moeten opnemen.  Je mag het doen, maar achter de schermen zou deze toch automatisch worden toegevoegd.

9.13.2. Meerdere Constructoren in Een Klasse

In 1 klasse kunnen meerdere constructoren worden opgenomen, dit is een vorm van method overloading.
Visual Basic 2012 Broncode - Codevoorbeeld 273
Class Teacher : Inherits Person
    Public Sub New(ByVal name As String)
        MyBase.New(name)
    End Sub
    Public Sub New(ByVal name As String, ByVal course As String)
        Me.New(name)
        Me.Course = course
    End Sub
    Public Property Course As String
End Class
Module Client4
    Sub Main()
        Dim teacher1 As Teacher = New Teacher("John")
        Console.WriteLine(teacher1.Name)
        Console.WriteLine(teacher1.Course)
        '
        Dim teacher2 As Teacher = New Teacher("Jane", "Visual Basic")
        Console.WriteLine(teacher2.Name)
        Console.WriteLine(teacher2.Course)
        '
        Console.ReadLine()
    End Sub
End Module
Console Application Output
John

Jane
Visual Basic
Een aanroep als Me.New(...) kan indien je in de constructor een andere constructor van die klasse wenst aan te roepen.
Deze call wordt verwezenlijkt nog voordat de constructor van de basisklasse wordt aangeroepen.

9.13.3. ReadOnly Velden

Naast ReadOnly properties (die enkel instelbaar zijn, en dus enkel over een "setter" beschikken) kan men ook ReadOnly velden declareren.

Aan deze ReadOnly velden kan enkel een waarde worden toegekend in de constructor.
Visual Basic 2012 Broncode - Codevoorbeeld 274
Class Product
    Public Sub New(ByVal taxPercentage As Decimal)
        _TaxPercentage = taxPercentage
    End Sub
    Private ReadOnly _TaxPercentage As Decimal
    Public ReadOnly Property TaxPercentage() As Decimal
        Get
            TaxPercentage = _TaxPercentage
        End Get
    End Property
    Public Property Price As Decimal
    Public Function GetPriceIncludingTax() As Decimal
        GetPriceIncludingTax = Price * (1 + (TaxPercentage / 100))
    End Function
End Class
Module Client5
    Sub Main()
        Dim product1 As Product = New Product(10)
        product1.Price = 100
        Console.WriteLine(product1.GetPriceIncludingTax())
        '
        Console.ReadLine()
    End Sub
End Module
Console Application Output
110
In bovenstaand voorbeeld wordt een TaxPercentage waarde beschouwd als een toestand die per Product object configureerbaar moet zijn (dus een instancegerelateerde toestand).  Hiervoor kunnen we dus een veld gebruiken om de toestandswaarde te stockeren.

Maar de TaxPercentage-toestand wordt hier ook beschouwd als een onwijzigbare toestand.  Wat we kunnen bekomen en garanderen door het gebruikte veld ReadOnly te declareren.

9.13.4. Oefeningen

Opgave 1 :

Wat is de uitvoer van volgend voorbeeld ?
Visual Basic 2012 Broncode - Codevoorbeeld 275
Module Exercise1Task
    Sub Main()
        Dim object2 As Class2 = New Class2
        '
        Console.WriteLine(object2.Value1)
        Console.WriteLine(object2.Value2)
        '
        Console.ReadLine()
    End Sub
End Module
Class Class1
    Public Value1 As Integer
    Public Sub New()
        Value1 = 1
    End Sub
End Class
Class Class2 : Inherits Class1
    Public Value2 As Integer
End Class
Oplossing 1 :
Console Application Output
1
0
Opgave 2 :
Wat is de uitvoer van volgend voorbeeld ?
Visual Basic 2012 Broncode - Codevoorbeeld 276
Module Exercise2Task
    Sub Main()
        Dim object4 As Class4 = New Class4
        '
        Console.WriteLine(object4.Value1)
        Console.WriteLine(object4.Value2)
        '
        Console.ReadLine()
    End Sub
End Module
Class Class3
    Public Value1 As Integer
    Public Sub New()
        Value1 = 3
    End Sub
End Class
Class Class4 : Inherits Class3
    Public Value2 As Integer
    Public Sub New()
        Value2 = Value1 * 4
    End Sub
End Class
Oplossing 2 :
Console Application Output
3
12
Opgave 3 :
Wat is de uitvoer van volgend voorbeeld ?
Visual Basic 2012 Broncode - Codevoorbeeld 277
Module Exercise3Task
    Sub Main()
        Dim object6 As Class6 = New Class6
        '
        Console.WriteLine(object6.Value1)
        Console.WriteLine(object6.Value2)
        '
        object6 = New Class6(10)
        '
        Console.WriteLine(object6.Value1)
        Console.WriteLine(object6.Value2)
        '
        Console.ReadLine()
    End Sub
End Module
Class Class5
    Public Value1 As Integer
    Public Sub New()
        Value1 = 2
    End Sub
    Public Sub New(ByVal value As Integer)
        Value1 = value
    End Sub
End Class
Class Class6 : Inherits Class5
    Public Value2 As Integer
    Public Sub New()
        MyBase.New(5)
        Value2 = Value1 * 6
    End Sub
    Public Sub New(ByVal value As Integer)
        MyBase.New()
        Value2 = Value1 * 6
    End Sub
End Class
Oplossing 3 :
Console Application Output
5
30
2
12
Opgave 4 :
Wat is de uitvoer van volgend voorbeeld ?
Visual Basic 2012 Broncode - Codevoorbeeld 278
Module Exercise4Task
    Sub Main()
        Dim object8 As Class8 = New Class8
        '
        Console.WriteLine(object8.Value1)
        Console.WriteLine(object8.Value2)
        '
        Console.ReadLine()
    End Sub
End Module
Class Class7
    Public Value1 As Integer
    Public Sub New()
    End Sub
    Public Sub New(ByVal value As Integer)
        Value1 = value
    End Sub
End Class
Class Class8 : Inherits Class7
    Public Value2 As Integer
End Class
Oplossing 4 :
Console Application Output
0
0
Opgave 5 :
Wat is de uitvoer van volgend voorbeeld ?
Visual Basic 2012 Broncode - Codevoorbeeld 279
Module Exercise5Task
    Sub Main()
        Dim object10 As Class10 = New Class10
        '
        Console.WriteLine(object10.Value1)
        Console.WriteLine(object10.Value2)
        '
        Console.ReadLine()
    End Sub
End Module
Class Class9
    Public Value1 As Integer
    Public Sub New()
    End Sub
    Public Sub New(ByVal value As Integer)
        Value1 = value
    End Sub
End Class
Class Class10 : Inherits Class9
    Public Value2 As Integer
    Public Sub New()
        Value2 = 2
    End Sub
End Class
Oplossing 5 :
Console Application Output
0
2
Opgave 6 :
Wat is de uitvoer van volgend voorbeeld ?
Visual Basic 2012 Broncode - Codevoorbeeld 280
Module Exercise6Task
    Sub Main()
        Dim object12 As Class12 = New Class12
        '
        Console.WriteLine(object12.Value1)
        Console.WriteLine(object12.Value2)
        '
        Console.ReadLine()
    End Sub
End Module
Class Class11
    Public Value1 As Integer
    Public Sub New()
    End Sub
    Public Sub New(ByVal value As Integer)
        Value1 = value
    End Sub
End Class
Class Class12 : Inherits Class11
    Public Value2 As Integer
    Public Sub New()
        MyBase.New(1)
        Value2 = 2
    End Sub
End Class
Oplossing 6 :
Console Application Output
1
2
Opgave 7 :
Wat is de uitvoer van volgend voorbeeld ?
Visual Basic 2012 Broncode - Codevoorbeeld 281
Module Exercise7Task
    Sub Main()
        Dim object14 As Class14 = New Class14(1, 2)
        '
        Console.WriteLine(object14.Value1)
        Console.WriteLine(object14.Value2)
        '
        Console.ReadLine()
    End Sub
End Module
Class Class13
    Public Value1 As Integer
    Public Sub New(ByVal value As Integer)
        Value1 = value
    End Sub
End Class
Class Class14 : Inherits Class13
    Public Value2 As Integer
    Public Sub New(ByVal value1 As Integer, ByVal value2 As Integer)
        MyBase.New(value1)
        Me.Value2 = value2
    End Sub
End Class
Oplossing 7 :
Console Application Output
1
2
Opgave 8 :
Schrijf een klasse Counter.  Van een Counter object kan je de waarde opvragen.  Voorzie ook methods om de waarde te verhogen en te verlagen.  De verhoog- en verlaag-stapwaarde mag hier steeds 1 zijn.

Het is verplicht bij het instantiëren van een Counter object een initiële waarde op te geven.
Oplossing 8 :
Visual Basic 2012 Broncode - Codevoorbeeld 282
Class Counter
    Public Sub New(ByVal value As Integer)
        _Value = value
    End Sub
    Protected _Value As Integer
    Public ReadOnly Property Value As Integer
        Get
           Value = _Value
        End Get
    End Function
    Public Sub Raise()
        _Value += 1
    End Sub
    Public Sub Lower()
        _Value -= 1
    End Sub
End Class
Module Exercise8Solution
    Sub Main()
        Dim counter1 As Counter = New Counter(5)
        Console.WriteLine(counter1.Value = 5)
        '
        Console.ReadLine()
    End Sub
End Module
Console Application Output
True

Dit artikel is gepubliceerd op maandag 15 oktober 2012 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.