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.10. Inheritance (Overerving) - Inherits

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.

9.10.1. Waarvoor is Inheritance Bruikbaar

Het kan voorkomen dat je nieuwe klasse die je wenst te definiëren zou willen baseren op een andere klasse.  Waarbij je dus stelt dat hetgeen dat gedefinieerd is in die andere klasse zou willen herbruiken in je nieuwe klasse.
Hier komt overerving (ook wel inheritance genoemd) van pas.  Inheritance zorgt ervoor dat de afgeleide klasse (derived/child class) alle members overneemt van de basisklasse (base/parent class).

Hieronder zie je een voorbeeld van inheritance.
Visual Basic 2012 Broncode - Codevoorbeeld 259
Class Person
    Public Property Name As String
End Class
Class Student : Inherits Person                                           ' (1)
    Public Property ClassGroup As String
End Class
De Student klasse erft hier over van de Person klasse, en neemt daarbij ook alle members over die gedefinieerd zijn in die basisklasse.  In onderstaande client kun je merken dat men op een object van het type Student nu ook de (overgeërfde) property Name kunt gebruiken.  Naast Name kan natuurlijk bijvoorbeeld ook ClassGroup worden gebruikt die in de klasse Student zelf werd gedefinieerd.
Visual Basic 2012 Broncode - Codevoorbeeld 260
Module Client1
    Sub Main()
        Dim person1 As Person = New Person
        person1.Name = "John"
        Console.WriteLine(person1.Name)
        '
        Dim student1 As Student = New Student
        student1.Name = "Jane"
        Console.WriteLine(student1.Name)
        student1.ClassGroup = "Group 1"
        Console.WriteLine(student1.ClassGroup)
        '
        Console.ReadLine()
    End Sub
End Module
Console Application Output
John
Jane
Group 1

9.10.2. Hoe Inheritance Gebruiken

Inheritance wordt toepast door in de afgeleide klasse een Inherits clausule op te nemen, ofwel op dezelfde regel als de identifier van de afgeleide klasse (met een : voor de Inherits clausule), ofwel met de Inherits clausule op de eerste regel van de klassedefinitie van de afgeleide klasse.
Visual Basic 2012 Broncode - Codevoorbeeld 261
Class Teacher
    Inherits Person
    Public Property Course As String
End Class

9.10.3. Single Inheritance

Zoals je hierboven merkt kan men van één basisklasse meerdere afgeleide klassen definiëren.  Men kan in Visual Basic echter wel slechts van één klasse overerven ("single inheritance"), in tegenstelling tot bepaalde andere OOPs waar men van meerdere klassen kan overerven ("multiple inheritance").

9.10.4. Single en Static Classification

Een object is in Visual Basic altijd een instantie van één bepaalde klasse ( "single classification"), dat type van object kan ook nooit wijzigen ( "static classification"), in tegenstelling tot sommige OOPs waar men een object kan maken van meerdere klassen ("multiple classification") of een object van type/klasse kan laten veranderen ("dynamic classification").

9.10.5. Wanneer Inheritance Toepassen

Wanneer inheritance van toepassing is tussen twee klassen, is er doorgaans een "is een" relatie tussen objecten van die twee entiteiten.  In dit voorbeeld kan je stellen een Student of een Teacher is een Person.
Verwar dit niet met de "heeft een" relatie die bij containment van toepassing is.
Enkele voorbeelden waarbij inheritance van toepassing zou kunnen zijn : een woonhuis is een gebouw, een wagen is een voertuig, een bediende is een werknemer, een tekstverwerker is een programma, ... .
Let echt op dat men gespecialiseerde (afgeleide) types niet verward met instanties, bijvoorbeeld John is een persoon.  Hierbij is John eerder een instanties, en niet zozeer een subtype.

Een afgeleide klasse kan ook een basisklasse vormen voor andere afgeleide klassen.
Eigenlijk dient gesteld te worden dat iedere klasse die je zelf definieert een afgeleide klasse is.  Voeg je zelf niet expliciet een Inherits clausule toe aan een klasse, dan staat er eigenlijk by default Inherits System.Object.  De klasse Person bijvoorbeeld is dus een afgeleide van het type System.Object.
Later wordt meer uitleg gegeven over dit overkoepelend basistype ( System.Object).

Inheritance zowel als containment zijn twee technieken om herbruik van code te verwezenlijken.  Bij containment kan je de members van het gerefereerde object aanspreken en dus herbruiken, bij inheritance worden de members gewoon overgeërfd, waardoor ze ook herbruikbaar zijn op of voor dat object van de afgeleide klasse.

Misbruik echter inheritance niet om simpelweg in uw afgeleide klasse de members niet te hoeven herdefiniëren die zijn overgeërfd.  De kracht van inheritance is immers niet zo zeer herbruik van code, maar eerder "dynamisch polymorfisme" waarbij objecten een andere gespecialiseerde vorm kunnen aannemen (later meer over polymorfisme).

Goede richtlijnen die je als vereiste kan hanteren voor het gebruik van inheritance zijn :
- de "is een" regel
- de "100 procent" regel : 100 procent van de members (of dus alle members) die gedefinieerd zijn in de basisklasse moeten ook bruikbaar zijn in de afgeleide klasse
Het valt aan te raden pas inheritance toe te passen indien aan beide regels voldaan is.

Anders gesteld zijn er twee invalshoeken om tot inheritance te komen :
- generalisatie : hier merk je dat verschillende klassen gemeenschappelijke members hebben, waarbij je dus de beslissing zou kunnen maken een basistype te definiëren waarin het gemeenschappelijke wordt gedefinieerd, ander typen die dan ook deze gemeenschappelijke members nodig hebben, kunnen dan ook van die basisklasse overerven
- specialisatie : hier bemerk je eerder dan een nieuw type dat je dient te definiëren eigenlijk een specialisatie is van een reeds bestaand type, waardoor je besluit van dat bestaand type over te erven en daaraan de gespecialiseerde kenmerken gaat toevoegen
Het resultaat is bij generalisatie of specialisatie hetzelfde, namelijk overerving, het zijn louter verschillende uitgangspunten van waaruit je kan vertrekken om tot inheritance te komen.

Onthoud voorlopig ook nog dat eens een member met een bepaalde signatuur is overgenomen uit een basisklasse, je niet zomaar in de afgeleide klasse een member kan toevoegen met dezelfde signatuur.  Later gaan we hier verder op in.

9.10.6. Een Ander Voorbeeld

We gaan in onderstaand voorbeeld uit van een klasse Counter, waarbij men op objecten van dit type de Value (tellerwaarde) kan opvragen (via de GetValue() method).  En waarbij de mogelijkheid bestaat via members in de publieke interface van dit type de Value te verhogen (Raise() method) of te verlagen (Lower() method).
Visual Basic 2012 Broncode - Codevoorbeeld 262
Class Counter
    Protected _Value As Integer
    Public Function GetValue() As Integer
        GetValue = _Value
    End Function
    Public Sub Raise()
        _Value += 1
    End Sub
    Public Sub Lower()
        _Value -= 1
    End Sub
End Class
Naderhand wensen we een gespecialiseerd type van Counter te creëren, namelijk een specialisatie waar het ook mogelijk wordt de Value in te stellen.

We beslissen hiervoor een afgeleide klasse SettableCounter te creëren en er een SetValue(...) method aan toe te voegen.

Allerhande redenen kunnen ervoor zorgen dat je Counter niet wil of kan wijzigen.  Het zou simpelweg kunnen voorvallen dat je niet wil riskeren om de bestaande klasse corrupt te maken.  Het zou ook kunnen dat je de abstractie van de klasse niet wil aanpassen, een waarde-instelbare en waarde-niet-instelbare teller is immers niet hetzelfde.  Het zou ook kunnen de je de basisklasse niet kan aanpassen omdat je niet over de broncode beschikt, en enkel over de gecompileerde klasse beschikt.
Visual Basic 2012 Broncode - Codevoorbeeld 263
Class SettableCounter : Inherits Counter
    Public Sub SetValue(ByVal value As Integer)
        _Value = value
    End Sub
End Class
Module Client2
    Sub Main()
        Dim counter1 As Counter = New Counter
        With counter1
            Console.WriteLine(.GetValue() = 0)
            .Raise()
            Console.WriteLine(.GetValue() = 1)
            .Lower()
            Console.WriteLine(.GetValue() = 0)
        End With
        '
        Dim specialCounter1 As SettableCounter = New SettableCounter
        With specialCounter1
            Console.WriteLine(.GetValue() = 0)
            .SetValue(10)
            Console.WriteLine(.GetValue() = 10)
            .Raise()
            Console.WriteLine(.GetValue() = 11)
            .Lower()
            Console.WriteLine(.GetValue() = 10)
        End With
        '
        Console.ReadLine()
    End Sub
End Module
Console Application Output
True
True
True
True
True
True
True

9.10.7. Access Modifier Protected

Zoals we reeds wisten zijn Private members enkel beschikbaar binnen de klasse zelf en zijn Public members overal (inclusief voor de client) bereikbaar.  Deze keywords geven aan of wijzigen dus het toegangs-/accessbereik van die members, vandaar de term "accessmodifiers".
De Protected members zijn best vergelijkbaar met Private members, alleen zijn ze niet louter binnen de klasse (waarin ze zijn gedefinieerd) beschikbaar, maar zijn ze ook toegankelijk voor de afgeleide klasse.  Clients echter hebben geen toegang tot deze members.

Het veld _Value gedefinieerd in de basisklasse Counter mag ingekapseld worden (dus niet Public) omdat het niet toegankelijk moet zijn voor de clients van Counter.
Afgeleide klassen van Counter zouden echter wel nut kunnen hebben aan toegang tot het veld _Value.  Zo geeft SettableCounter het veld _Value nodig om in de SetValue method de Value toestand te kunnen wijzigen.  Daarom kan hier aan het veld _Value hier een Protected access modifier worden gegeven.

Men zou dus steeds bij het opnemen van ingekapselde members (niet publieke members) moeten nagaan of afgeleiden nut kunnen hebben aan toegang tot deze member.  Hebben de afgeleiden geen nut aan toegang tot die member dan kan die member als Private worden gedefinieerd, is er wel nut voor de afgeleiden aan toegang tot die member dan kan deze member als Protected worden gedefinieerd.

Voor alle duidelijkheid dus nog eens stellen : Public members die zijn overgeërfd zijn ook beschikbaar voor client op objecten van dat afgeleid type.
Vergis je echter niet : niet alleen Public en Protected members worden overgeërfd, ook de Private members worden overgenomen, alleen zijn die niet toegankelijk, zelfs niet voor afgeleide klassen.  Het gebruik van Private en Protected members is dus een vorm van encapsulation ( inkapseling) waarvan het gebruik van die members voor de client ( Protected) en eventueel ook voor de afgeleide klasse zelf (Private) verhinderd wordt.

9.10.8. Oefeningen

Opgave 1 :

Maak de nodige klassen om voorstellingen van personeelsleden te kunnen maken.
Een personeelslid heeft als eigenschappen : een naam en een adres (een adres houdt in een straat, een huisnummer, een postcode en een gemeente).

Zorg er ook voor dat we voorstellingen kunnen maken van managers.
Managers zijn personeelsleden met meer verantwoordelijkheden en hebben als eigenschappen : een naam, een adres en een wagen (van een bepaald merk).
Oplossing 1 :
Visual Basic 2012 Broncode - Codevoorbeeld 264
Class Address
    Public Property Street As String
    Public Property Number As String
    Public Property ZipCode As String
    Public Property City As String
End Class
Class Employee
    Public Property Name As String
    Public Property Address As Address
End Class
Class Manager : Inherits Employee
    Public Property Car As Car
End Class
Class Car
    Public Property Brand As String
End Class
Opgave 2 :
Hieronder worden een aantal zelfstandige naamwoorden of eigennamen vermeld :

Hollande, monarch, Paris, country, United Kingdom, president, monarchy, France, capital, London, Elizabeth, republic

Gebruik zelf alle bovenvermelde woorden in uw oplossing.  Kies zelf of het woord best past als klasse-identifier, member-identifier, toestandswaarde of object-identifier.

Pas inheritance toe, daar waar je denkt dat het nuttig is.
Oplossing 2 :
Visual Basic 2012 Broncode - Codevoorbeeld 265
Module Exercise2Solution
    Sub Main()
        Dim france As Republic = New Republic
        france.Capital = "Paris"
        france.President = "Hollande"
        '
        Dim unitedKingdom As Monarchy = New Monarchy
        unitedKingdom.Capital = "London"
        unitedKingdom.Monarch = "Elizabeth"
    End Sub
End Module
Class Country
    Public Property Capital As String
End Class
Class Monarchy : Inherits Country
    Public Property Monarch As String
End Class
Class Republic : Inherits Country
    Public Property President As String
End Class

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