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

20.3. Abstracte Members

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.

20.3.1. MustOverride

Niet alleen een klasse zelf kunnen we abstract maken, ook members kunnen abstract worden gemaakt.  Deze abstracte members hebben een signatuur (zijn aanwezig in een klasse met een bepaalde interface), maar hebben geen implementatie.

Uiteraard kunnen we dergelijke members enkel in een abstracte klasse definiëren, want anders zouden we voor objecten van concrete types die members kunnen aanroepen, zonder dat geweten is welke implementatie aan die aanroep moet gekoppeld worden (welke binding moet worden gebruikt).

Een member maak je abstract via het keyword MustOverride, en de definitie hiervan bestaat enkel uit de signatuurregel.  Een concreet afgeleide klasse is dan verplicht een Overrides implementatie te gaan binden aan die memberinterface die hij van die abstracte klasse heeft overgeërfd.

Alle figuren in ons systeem (alle afgeleide types van Figure) zouden bijvoorbeeld nut hebben aan een member die de oppervlakte (GetArea()) oplevert.
Gezien deze member voor alle soorten van figuren van toepassing is, kunnen we deze member best in het generalisatietype Figure opnemen, zo kan de member worden overgenomen naar alle gespecialiseerde afgeleide types.
We kunnen echter moeilijk een implementatie koppelen aan die member omdat er simpelweg geen algemene formule bestaat voor het bepalen van de oppervlakte die voor alle gespecialiseerde soorten figuren van toepassing is.
Dit is geen probleem we kunnen die member als abstracte member ( MustOverride member) opnemen in het generalisatietype Figure, alle concrete afgeleide types kunnen/moeten daarvoor dan een implementatie voorzien (Overrides implementatie).
Visual Basic 2012 Broncode - Codevoorbeeld 446
MustInherit Class Figure
    Public Property Color As String
    Protected Sub New(ByVal color As String)
        Me.Color = color
    End Sub
    Public MustOverride Function GetArea() As Double                       ' (1)
End Class
Class Rectangle : Inherits Figure
    Public Property Height As Double
    Public Property Width As Double
    Public Sub New(ByVal color As String, _
                   ByVal height As Double, ByVal width As Double)
        MyBase.New(color)
        Me.Height = height
        Me.Width = width
    End Sub
    Public Overrides Function GetArea() As Double
        GetArea = Height * Width
    End Function
End Class
Class Circle : Inherits Figure
    Public Property Radius As Double
    Public Sub New(ByVal color As String, _
                   ByVal radius As Double)
        MyBase.New(color)
        Me.Radius = radius
    End Sub
    Public Overrides Function GetArea() As Double
        GetArea = Radius ^ 2 * System.Math.PI
    End Function
End Class
Class Example1
    Public Shared Sub Main()
        Dim rectangle1 As Rectangle = New Rectangle("red", 10, 20)
        Console.WriteLine(rectangle1.GetArea())
        '
        Dim circle1 As Circle = New Circle("yellow", 10)
        Console.WriteLine(circle1.GetArea())
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
200
314,159265358979
De abstracte member (1) wordt dus gedefinieerd door het MustOverride keyword, en bestaat dus enkel uit de signatuur van die member.  Public is hier opgenomen in de signatuur, omdat we wensen dat Area ook beschikbaar is in de publieke interface van die afgeleide types, en clients dus op die gespecialiseerde Figure objecten die member kunnen aanroepen.

Enkel implementatiemembers (methods en properties) kunnen als MustOverride worden gedefinieerd.  De herdefinitie (bijhorende Overrides) moet voorzien in een nieuwe implementatie voor die member.
Een member zonder implementatie (zoals een field) kan ook moeilijk gebonden worden aan een nieuwe implementatie.

De Private members kunnen ook niet als MustOverride worden gemarkeerd.
Gezien er geen interface naar die member (aanwezigheid van die member in de interface) wordt overgeërfd, kan deze niet overgenomen interface niet geherdefinieerd worden.

Enkel concrete afgeleide klassen moeten een implementatie voorzien voor de overgeërfde abstracte member.  Is de afgeleide klasse zelf abstract dan kan (1), maar hoeft deze klasse geen implementatie te voorzien (2).
Visual Basic 2012 Broncode - Codevoorbeeld 447
MustInherit Class Class1
    MustOverride Sub Method1()
End Class
MustInherit Class Class2 : Inherits Class1
    '                                                                        (2)
End Class
Class Class3 : Inherits Class2
    Public Overrides Sub Method1()                                         ' (1)
        Console.WriteLine("Class3.Method1()")
    End Sub
End Class
Class Class4 : Inherits Class3
End Class
MustInherit Class Class5 : Inherits Class1
    Public Overrides Sub Method1()                                         ' (1)
        Console.WriteLine("Class5.Method1()")
    End Sub
End Class
Class Class6 : Inherits Class5
End Class
Class Example2
    Public Shared Sub Main()
        'Dim object1 As Class1 = New Class1 ' not possible, abstract class
        'Dim object2 As Class2 = New Class2 ' not possible, abstract class
        Dim object3 As Class3 = New Class3
        object3.Method1()
        Dim object4 As Class4 = New Class4
        object4.Method1()
        'Dim object5 As Class5 = New Class5 ' not possible, abstract class
        Dim object6 As Class6 = New Class6
        object6.Method1()
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
Class3.Method1()
Class3.Method1()
Class5.Method1()
Dat abstracte klassen die een abstracte member overerven geen implementatie moeten voorzien voor die member is niet zo vreemd.  Van dat afgeleide type zelf kan immers toch geen object worden aangemaakt waarop die members zou worden aangeroepen en waaraan dus een implementatie zou gekoppeld worden.

Dat concrete afgeleide klassen die een abstracte member overerven wel een implementatie moeten voorzien is ook logisch, want hiervan kunnen wel objecten worden aangemaakt waarop die member kan worden aangeroepen en waaraan dus wel een implementatie zou moeten worden gekoppeld.
Visual Basic 2012 Broncode - Codevoorbeeld 448
Class Example3
    Public Shared Sub Main()
        Dim figure1 As Figure = New Rectangle("red", 10, 20)
        Console.WriteLine(figure1.GetArea())
        Console.WriteLine(figure1.Color)
        Console.WriteLine()
        '
        Dim figure2 As Figure = New Circle("yellow", 10)
        Console.WriteLine(figure2.GetArea())
        Console.WriteLine(figure2.Color)
        Console.WriteLine()
        '
        Dim figures As Figure() = _
                         New Figure() {figure1, figure2, New Circle("red", 100)}
        For Each figure As Figure In figures
            Console.WriteLine(figure.GetArea())
            Console.WriteLine(figure.Color)
            Console.WriteLine()
        Next
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
200
red

314,159265358979
yellow

200
red

314,159265358979
yellow

31415,9265358979
red
Bovenstaande client verduidelijkt nogmaals dat we in een variabele gedeclareerd van een basis type (Figure) een referentie kunnen stockeren van een object van een afgeleid type (Rectangle of Circle).

Het is dus niet omdat het een abstract type is, dat je er geen variabele van zou kunnen declareren, enkel dergelijk object (van abstract type) instantiëren kan niet.

De array figures gedeclareerd met elementen van het type Figure kan referenties bevatten van Rectangle  en Circle objecten.
Maar op de figure expressie gedeclareerd van het type Figure en gebruikt in de For Each ... Next kan men dan enkel de members aanroepen die gedefinieerd zijn in het statisch type van die expressie ( Figure).  Dus enkel de members GetArea() en Color zijn beschikbaar, de gespecialiseerde Height, Width en Radius members zijn pas beschikbaar indien casting wordt toegepast.

20.3.2. Oefening

Opgave :

Gegeven zijn onderstaande (correcte) klassen en hun members :
Visual Basic 2012 Broncode - Codevoorbeeld 449
MustInherit Class Class_1
    Public MustOverride Sub Command1()
    Public Overridable Sub Command2()
        Console.WriteLine("Class_1.Command2()")
    End Sub
End Class
Class Class_2 : Inherits Class_1
    Public Overrides Sub Command1()
        Console.WriteLine("Class_2.Command1()")
    End Sub
    Public Overridable Sub Command3()
        Console.WriteLine("Class_2.Command3()")
    End Sub
    Public Overridable Sub Command4()
        Console.WriteLine("Class_2.Command4()")
    End Sub
End Class
MustInherit Class Class_3 : Inherits Class_1
    Public MustOverride Sub Command4()
    Public Overridable Sub Command5()
        Console.WriteLine("Class_3.Command5()")
    End Sub
End Class
MustInherit Class Class_4 : Inherits Class_3
    Public Overrides Sub Command1()
        Console.WriteLine("Class_4.Command1()")
    End Sub
    Public Overrides Sub Command2()
        Console.WriteLine("Class_4.Command2()")
    End Sub
    Public Overridable Sub Command6()
        Console.WriteLine("Class_4.Command6()")
    End Sub
End Class
Class Class_5 : Inherits Class_4
    Public Overrides Sub Command4()
        Console.WriteLine("Class_5.Command4()")
    End Sub
    Public Overrides Sub Command5()
        Console.WriteLine("Class_5.Command5()")
    End Sub
    Public Overridable Sub Command7()
        Console.WriteLine("Class_5.Command7()")
    End Sub
End Class
Gegeven zijn onderstaande (deels foutieve) klasse en zijn members.

Onderzoek de implementaties van onderstaande boodschappen Query1(), Query2() en Query3() en leg uit wat er verkeerd aan is.
Visual Basic 2012 Broncode - Codevoorbeeld 450
Class Class_6
    'Public Function Query1() As Class_1
    '    Query1 = New Class_3
    'End Function
    'Public Function Query2() As Class_2
    '    Query2 = New Class_5
    'End Function
    'Public Function Query3() As Class_1
    '    Query3 = New Class_5
    'End Function
    'Public Sub Command1(ByVal parameter As Class_3)
    '    parameter.Command4()
    'End Sub
    'Public Sub Command2(ByVal parameter As Class_1)
    '    parameter.Command2()
    'End Sub
End Class
Voor verder onderzoek veronderstellen we dat de foutieve members uit bovenstaande klasse zijn verwijderd.

Onderzoek de uitvoer of wat fout loopt bij elk van onderstaande regels.
Ga na of er fouten zullen optreden, welke deze zijn, en ga na welke de uitvoer zou zijn (indien geen fouten).
Visual Basic 2012 Broncode - Codevoorbeeld 451
Class Exercise1Task
    Public Shared Sub Main()
        'Dim object1 As Class_1 = New Class_5
        'object1.Command1()
        'object1.Command2()
        'object1.Command3()
        'object1.Command4()
        'object1.Command5()
        'object1.Command6()
        'object1.Command7()
        ''
        'Dim object2 As Class_2 = New Class_2
        'object2.Command1()
        'object2.Command2()
        'object2.Command3()
        'object2.Command4()
        'object2.Command5()
        'object2.Command6()
        'object2.Command7()
        ''
        'Dim object3 As Class_3 = New Class_5
        'object3.Command1()
        'object3.Command2()
        'object3.Command3()
        'object3.Command4()
        'object3.Command5()
        'object3.Command6()
        'object3.Command7()
        ''
        'Dim object4 As Class_5 = New Class_5
        'object4.Command1()
        'object4.Command2()
        'object4.Command3()
        'object4.Command4()
        'object4.Command5()
        'object4.Command6()
        'object4.Command7()
        ''
        'Dim object5 As Class_6 = New Class_6
        'object5.Command1(object1)
        'object5.Command1(object2)
        'object5.Command1(object3)
        'object5.Command1(object4)
        'object5.Command2(object1)
        'object5.Command2(object2)
        'object5.Command2(object3)
        'object5.Command2(object4)
        'object5.Query3().Command1()
        'object5.Query3().Command2()
        'object5.Query3().Command3()
        'object5.Query3().Command4()
        'object5.Query3().Command5()
        'object5.Query3().Command6()
        'object5.Query3().Command7()
    End Sub
End Class
Oplossing :
Visual Basic 2012 Broncode - Codevoorbeeld 452
Class Class_6
    'Public Function Query1() As Class_1
    '    Query1 = New Class_3
    'End Function
    'Public Function Query2() As Class_2
    '    Query2 = New Class_5
    'End Function
    Public Function Query3() As Class_1
        Query3 = New Class_5
    End Function
    Public Sub Command1(ByVal parameter As Class_3)
        parameter.Command4()
    End Sub
    Public Sub Command2(ByVal parameter As Class_1)
        parameter.Command2()
    End Sub
End Class
- Query1() is foutief, Class_3 is abstract en kan niet geïnstantieerd worden (1).
- Query2() is foutief, Class_5 is niet afgeleid van Class_2 (2).
- Query3() is correct.
Visual Basic 2012 Broncode - Codevoorbeeld 453
Class Exercise1Solution
    Public Shared Sub Main()
        Dim object1 As Class_1 = New Class_5 ' ok
        object1.Command1()  ' output : "Class_4.Command1()"
        object1.Command2()  ' output : "Class_4.Command2()"
        'object1.Command3() ' impossible, no 'Command3()' in 'Class_1'
        'object1.Command4() ' impossible, no 'Command4()' in 'Class_1'
        'object1.Command5() ' impossible, no 'Command5()' in 'Class_1'
        'object1.Command6() ' impossible, no 'Command6()' in 'Class_1'
        'object1.Command7() ' impossible, no 'Command7()' in 'Class_1'
        '
        Dim object2 As Class_2 = New Class_2 ' ok
        object2.Command1()  ' output : "Class_2.Command1()"
        object2.Command2()  ' output : "Class_1.Command2()"
        object2.Command3()  ' output : "Class_2.Command3()"
        object2.Command4()  ' output : "Class_2.Command4()"
        'object2.Command5() ' impossible, no 'Command5()' in 'Class_2'
        'object2.Command6() ' impossible, no 'Command6()' in 'Class_2'
        'object2.Command7() ' impossible, no 'Command7()' in 'Class_2'
        '
        Dim object3 As Class_3 = New Class_5 ' ok
        object3.Command1()  ' output : "Class_4.Command1()"
        object3.Command2()  ' output : "Class_4.Command2()"
        'object3.Command3() ' impossible, no 'Command3()' in 'Class_3'
        object3.Command4()  ' output : "Class_5.Command4()"
        object3.Command5()  ' output : "Class_5.Command5()"
        'object3.Command6() ' impossible, no 'Command6()' in 'Class_3'
        'object3.Command7() ' impossible, no 'Command7()' in 'Class_3'
        '
        Dim object4 As Class_5 = New Class_5 ' ok
        object4.Command1()  ' output : "Class_4.Command1()"
        object4.Command2()  ' output : "Class_4.Command2()"
        'object4.Command3() ' impossible, no 'Command3()' in 'Class_5'
        object4.Command4()  ' output : "Class_5.Command4()"
        object4.Command5()  ' output : "Class_5.Command5()"
        object4.Command6()  ' output : "Class_4.Command6()"
        object4.Command7()  ' output : "Class_5.Command7()"
        '
        Dim object5 As Class_6 = New Class_6 ' ok
        'object5.Command1(object1) ' typefout : Class_1 geen subtype van Class_3
        'object5.Command1(object2) ' typefout : Class_1 geen subtype van Class_3
        object5.Command1(object3)  ' output : "Class_5.Command4()"
        object5.Command1(object4)  ' output : "Class_5.Command4()"
        object5.Command2(object1)  ' output : "Class_4.Command2()"
        object5.Command2(object2)  ' output : "Class_1.Command2()"
        object5.Command2(object3)  ' output : "Class_4.Command2()"
        object5.Command2(object4)  ' output : "Class_4.Command2()"
        object5.Query3().Command1()  ' output : "Class_4.Command1()"
        object5.Query3().Command2()  ' output : "Class_4.Command2()"
        'object5.Query3().Command3() ' impossible, no 'Command3()' in 'Class_1'
        'object5.Query3().Command4() ' impossible, no 'Command4()' in 'Class_1'
        'object5.Query3().Command5() ' impossible, no 'Command5()' in 'Class_1'
        'object5.Query3().Command6() ' impossible, no 'Command6()' in 'Class_1'
        'object5.Query3().Command7() ' impossible, no 'Command7()' in 'Class_1'
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
Class_4.Command1()
Class_4.Command2()
Class_2.Command1()
Class_1.Command2()
Class_2.Command3()
Class_2.Command4()
Class_4.Command1()
Class_4.Command2()
Class_5.Command4()
Class_5.Command5()
Class_4.Command1()
Class_4.Command2()
Class_5.Command4()
Class_5.Command5()
Class_4.Command6()
Class_5.Command7()
Class_5.Command4()
Class_5.Command4()
Class_4.Command2()
Class_1.Command2()
Class_4.Command2()
Class_4.Command2()
Class_4.Command1()
Class_4.Command2()

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