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

11.2. Dynamic Binding

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.

We weten dat we op een objectexpressie alle publieke members kunnen aanroepen uit het bijhorende statisch type van de expressie.

Tot nu toe wees een expressie van een bepaald statisch type ook steeds (at runtime) naar een object van datzelfde type (zoals (1) en (2)).

Toch hoeft dit niet altijd zo te zijn, een variabele gedeclareerd van een basistype kan ook opgevuld zijn met een referentie van een object van een afgeleid type (zoals (3)).

Het "eigenlijke" type van object waarnaartoe een objectexpressie wijst at runtime (tijdens uitvoering) wordt ook wel het dynamisch type van een expressie genoemd.

Het statisch en dynamisch type van een expressie hoeft dus niet overeen te komen, weliswaar moet het dynamisch type op zen minst een afgeleide zijn van het statisch type van de expressie.
Visual Basic 2012 Broncode - Codevoorbeeld 304
Class Person
End Class
Class Student : Inherits Person
End Class
Class Example1
    Public Shared Sub Main()
        Dim person1 As Person = New Person   ' (1)
        ' person1 : static (Person) = dynamic (Person)
        '
        Dim person2 As Student = New Student ' (2)
        ' person2 : static (Student) = dynamic (Student)
        '
        Dim person3 As Person = New Student  ' (3)
        ' person3 : static (Person) <> dynamic (Student)
    End Sub
End Class
De motivatie om een referentie van een object van een afgeleid type te stockeren in een variabele gedeclareerd van het basistype is vooral de opgeleverde flexibiliteit.  Alle objecten (zowel Person- als Student objecten bijvoorbeeld) kunnen op dezelfde manier behandeld worden.
Of het dynamisch type nu Person of Student is, steeds kan de verwijzing naar dergelijk object in een variabele van het statisch type Person gestockeerd worden.
Je zou dus kunnen zeggen dat een Student object (dynamisch type Student) zich in de vorm van een Student of Person kan bevinden.

11.2.1. Liskov Substitution Principle

Uit vorige voorbeelden weten we reeds dat het statisch type van een expressie van belang is voor het bepalen (door de compiler) welke boodschappen op een objectexpressie kunnen worden aangeroepen.

Dat de compiler hiervoor werkt met het statisch type van een expressie is logisch gezien at compiletime (en dus voor runtime) het dynamisch type van de expressie nog niet gekend is.
Visual Basic 2012 Broncode - Codevoorbeeld 305
Partial Class Person
    Public Property Name As String
End Class
Class Example2
    Public Shared Sub Main()
        Dim person1 As Person = New Person With {.Name = "John"}           ' (1)
        ' person1 : static (Person) = dynamic (Person)
        Console.WriteLine(person1.Name)
        '
        Dim person2 As Student = New Student With {.Name = "Jane"}         ' (2)
        ' person2 : static (Student) = dynamic (Student)
        Console.WriteLine(person2.Name)
        '
        Dim person3 As Person = New Student With {.Name = "Paul"}          ' (3)
        ' person3 : static (Person) <> dynamic (Student)
        Console.WriteLine(person3.Name)
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
John
Jane
Paul
Op de expressie person1 die gedeclareerd is als een variabele van het type Person (As Person), kunnen we de member Name aanroepen omdat deze behoort tot de publieke interface van het type Person (Name behoort tot het statisch type van person1 en person3).

Op de expressie person2 die gedeclareerd is als een variabele van het type Student (As Student), kunnen we ook de publieke member Name aanroepen omdat deze ook tot de publieke interface behoort van het type Student ( Name behoort tot het statisch type van person2).  Student heeft Name tenslotte overgeërfd van Person.

Maar ook op de expressie person3 kunnen we probleemloos de Name eigenschap aanroepen gezien Name zich bevindt in het statisch type van person3 (Name zicht dus bevindt in Person).

Het aanroepen van een member uit de interface van het basistype op een objectexpressie met het basistype als statisch type maar een afgeleid type als dynamisch type, zal nooit problemen opleveren, gezien dat afgeleid object ook altijd zal beschikken over dergelijke member.  Deze member is minstens overgeërfd, en al dan niet geherdefinieerd door de afgeleide klasse.

Sterker nog, men kan zeggen : overal waar men een instantie van de basisklasse kan gebruiken kan men deze instantie vervangen door een instantie van de afgeleide klasse (Liskov Substitution Principle (ook afgekort als LSP)).

11.2.2. Dynamic Binding

Visual Basic gebruik net zoals alle OOPs dynamic binding.

De kracht van inheritance is niet zozeer het herbruik van members met hun eventuele bijhorende implementaties, maar eerder dynamisch polymorfisme.

Polymorfisme houdt letterlijk in : het kunnen aannemen van vele ("poly") verschillende vormen ("morph").

In onderstaand voorbeeld hebben we een Counter klasse waar men de Value kan van opvragen, en waar men de Value kan doen toenemen met één (via de Raise() method).  Een specialisatie klasse SpecialCounter wordt ook voorzien, waar men bijkomend een stap waarde (StepValue) kan opgeven om niet steeds de Value met één te hoeven verhogen.
Visual Basic 2012 Broncode - Codevoorbeeld 306
Class Counter
    Protected _Value As Integer
    Public Sub New(ByVal value As Integer)
        _Value = value
    End Sub
    Public ReadOnly Property Value() As Integer
        Get
            Value = _Value
        End Get
    End Property
    Public Overridable Sub Raise()
        _Value += 1
    End Sub
End Class
Class SpecialCounter : Inherits Counter
    Public Sub New(ByVal value As Integer, ByVal stepValue As Integer)
        MyBase.New(value)
        Me.StepValue = stepValue
    End Sub
    Public Property StepValue As Integer
    Public Overrides Sub Raise()
        _Value += StepValue
    End Sub
End Class
Class Example3
    Public Shared Sub Main()
        Dim counter1 As Counter = New Counter(10)
        Console.WriteLine(counter1.Value)
        counter1.Raise()
        Console.WriteLine(counter1.Value)
        '
        Dim counter2 As Counter = New SpecialCounter(20, 5)
        Console.WriteLine(counter2.Value)
        counter2.Raise()                                                  ' (1)
        Console.WriteLine(counter2.Value)                                 ' (2)
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
10
11
20
25
Het statisch type van de expressie counter2 is Counter, het dynamisch type van deze expressie is echter SpecialCounter.  Op regel (1) zien we dat de method Raise() wordt aangeroepen op de ontvanger expressie counter2, dit is mogelijk gezien het statisch type van die ontvangerexpressie ( Counter) in zijn interface een method Raise() voorziet.

Aan de uitvoer van regel (2) zien we echter dat die call naar de Raise() method uit Counter (1) gebonden werd aan de (Overrides) implementatie gedefinieerd in het afgeleide type SpecialCounter.  De implementatie gedefinieerd in het dynamisch type van counter2 (zijnde SpecialCounter) werd hier uitgevoerd.

Welke members men kan aanroepen op een ontvangerexpressie is afhankelijk van het statisch type van die expressie, dit wordt door de compiler gecontroleerd om typefouten te vermijden.

Aan welke implementatie een membercall op een ontvangerexpressie gebonden wordt is afhankelijk van het dynamisch type, dat at runtime wordt bepaald.

Visual Basic gebruikt dus in bepaalde gevallen dynamische binding.
Hierbij kan dus slechts tijdens uitvoering van het programma bepaald worden hoe een bepaalde membercall moet worden vertaald in een sprong naar de juiste implementatie.  Dit gebeurt slechts tijdens uitvoering omdat pas dan het dynamische type van een expressie kan worden bepaald, gezien deze kan variëren tijdens runtime.
Een performantere vorm van binding is statisch binding.  Hierbij wordt tijdens het compileren reeds deze vertaling gemaakt, en hoeft er dus ( tijdens uitvoering) geen tijd aan verloren te gaan.
Om de performantie te bevorderen gebruikt Visual Basic niet altijd dynamisch binding.  Een call naar een Private member bijvoorbeeld kan steeds statisch gebonden worden.  Een Private member kan nooit geherdefinieerd worden, gezien het enkel in de klasse zelf toegankelijk is.
Het type van een expressie tijdens uitvoering kan in dergelijk geval dus nooit een criterium vormen voor het bepalen welke klasse de implementatie bevat die moet worden uitgevoerd.  Dus meteen (at compiletime) kan deze membercall reeds vertaald worden in een sprong naar de implementatie in de klasse zelf.
Dynamische binding is in dergelijke situatie dus niet nodig.  Ook andere gevallen waarin men afwijkt van dynamische binding bestaan, deze - net zoals de mogelijkheid om expliciet aangegeven af te wijken van dynamische binding - worden verderop behandeld.

Sommige programmeertalen beschikken enkel over statische binding, dit zijn per definitie geen object geörienteerde talen.  Want dan wordt het dynamisch type van een ontvangerexpressie (of het type van een expressie tijdens uitvoering) nooit gebruikt om te bepalen welke implementatie moet worden uitgevoerd, en kan er dus bijgevolg nooit sprake zijn van bijvoorbeeld redefinition, of dus dynamisch polymorfisme.
Dynamisch polymorfisme is immers een van de basiskenmerken van een object geörienteerde taal.

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