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.7. Containment

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.7.1. Een Verband tussen Objecten

Vaak komt het voor dat objecten van (verschillende) types een verband met elkaar hebben.  Dat beide types dus geassocieerd zijn.
Dergelijke associatie kan ontstaan wanneer één object een (ander) object heeft.  Van hier spreek ik in dat geval over een containment-relatie, die doorgaans gekenmerkt wordt door de "heeft-een" relatie tussen de entiteiten.

Bijvoorbeeld : een Person heeft een Address.
Visual Basic 2012 Broncode - Codevoorbeeld 239
Class Person
    Public Property Name As String
    Private _Address As Address
    Public Property Address() As Address
        Get
            Address = _Address
        End Get
        Set(ByVal value As Address)
            _Address = value
        End Set
    End Property
    'or: Public Property Address As Address
End Class
Class Address
    Public Property Street As String
    Public Property Number As String
    Public Property ZipCode As String
    Public Property City As String
End Class
Module Client1
    Sub Main()
        Dim address1 As Address = New Address
        address1.Street = "Royal Avenue"
        address1.Number = "10"
        address1.ZipCode = "90210"
        address1.City = "Beverly Hills"
        '
        Dim person1 As Person = New Person
        person1.Name = "John"
        person1.Address = address1
        '
        Print(person1)
        '
        Console.ReadLine()
    End Sub
    Sub Print(ByVal person As Person)
        Console.WriteLine(person.Name)
        If person.Address IsNot Nothing Then
            With person.Address
                Console.WriteLine(.Number & ", " & .Street)
                Console.WriteLine(.City & " " & .ZipCode)
            End With
        End If
    End Sub
End Module
Console Application Output
John
10, Royal Avenue
Beverly Hills 90210
Het With [object-expression] ... End With blok is bruikbaar om tussen With en End With op verkorte wijze (men kan de objectexpressie zelf weglaten) te verwijzen naar de members van het object waarnaartoe deze objectexpressie verwijst.

Een object van de klasse Person kan hier beschikken over een referentie van een Address object.  Op deze wijze kan een associatie tussen deze 2 entiteiten worden bijgehouden.

In bovenstaande Main procedure wordt eerst een variabele (address1) opgevuld met de referentie van een nieuw Address object, om deze vervolgens te gebruiken als setvalue voor de eigenschap Address van Person.

Op zich zou men het gebruik van deze variabele (address1) kunnen vermijden.
Visual Basic 2012 Broncode - Codevoorbeeld 240
Module Client2
    Sub Main()
        Dim person1 As Person = New Person
        person1.Name = "John"
        person1.Address = New Address
        person1.Address.Street = "Royal Avenue"                            ' (1)
        person1.Address.Number = "10"
        person1.Address.ZipCode = "90210"
        person1.Address.City = "Beverly Hills"
        Print(person1)
        '
        Dim person2 As Person = New Person
        person2.Name = "Jane"
        person2.Address = person1.Address                                  ' (2)
        Print(person2)
        '
        Console.ReadLine()
    End Sub
End Module
Console Application Output
John
10, Royal Avenue
Beverly Hills 90210
Bemerk de doorgedreven puntnotatie dat gebruikt kan worden om bijvoorbeeld te verwijzen naar de eigenschap Street van het Address van een Person (1).

9.7.2. Herbruik van Klassen en Code

Bemerk ook hoe eenvoudig het is om verschillende personen gebruik te laten maken van hetzelfde adres (hetzelfde Address object) (2).
Dit kan natuurlijk enkel doordat Address een aparte constructie is.  Hadden we de eigenschappen Street, Number, ZipCode en City in de constructie Person opgenomen, dan hadden we voor deze personen (person1 en person2) de adresgegevens moeten dupliceren.

In bovenstaand voorbeeld werd ervoor ge-opteerd de client een object van het type Address te laten instantiëren, en vervolgens toe te kennen aan de eigenschap Address van het Person object.

Het alternatief is objecten van het Person type zelf een object van het type Address te laten instantiëren, zoals in onderstaand voorbeeld gebeurt in de Customer klasse (1).
Visual Basic 2012 Broncode - Codevoorbeeld 241
Class Customer
    Public Property Name As String
    Private _Address As Address = New Address                             ' (1)
    Public Property Address() As Address
        Get
            Address = _Address
        End Get
        Set(ByVal value As Address)
            _Address = value
        End Set
    End Property
    'or: Public Property Address As Address = New Address
End Class
Het verschil zit hem hier in regel (1) waar het veld _Address meteen geïnitialiseerd wordt met een verwijzing naar een nieuw geïnstantieerd object van het type Address.

Hierbij is het niet meer nodig de client zelf een object te laten maken van deze Address klasse.
Visual Basic 2012 Broncode - Codevoorbeeld 242
Module Client3
    Sub Main()
        Dim customer1 As Customer = New Customer
        customer1.Address.City = "New York"
        '
        Console.WriteLine(customer1.Address.City)
        '
        Console.ReadLine()
    End Sub
End Module
Console Application Output
New York

9.7.3. Wie is Verantwoordelijk voor het Creëren van een Object

Of men al dan niet het contained object laat creëren door het containing object is afhankelijk van een aantal factoren.

Indien het containing object de enigste is die moet beschikken over het contained object, of indien het containing object beschikt over de kennis welke de initialisatiedata is voor het contained object, dan zal men waarschijnlijk het containing object verantwoordelijk maken voor het creëren van het contained object ("GRASPattern Creator").

In dit geval zou je kunnen stellen dat een adres door meerdere personen of klanten kan gedeeld worden.  Het lijkt dan ook het meest voor de hand liggend om de client verantwoordelijk te maken voor het expliciet instantiëren van een Address object.

Je ziet ook hoe het mogelijk is in meerdere klassen (als Person en Customer) dezelfde klasse (als Address) te herbruiken.  Containment kan dus leiden tot het herbruik van code.

Andere voorbeelden van containment kunnen zijn : een computer heeft een processor, een factuur heeft een klant (of anders gesteld een factuur is van toepassing op een klant), een wagen heeft een motor, een boek heeft een index, ... .

9.7.4. Oefeningen

Opgave 1 :

Pas de klasse Robot uit vorig onderwerp aan.  Laat een Robot gebruik maken van een Position, die een positie op een XY-assenstelsel voorstelt.
Oplossing 1 :
Visual Basic 2012 Broncode - Codevoorbeeld 243
Class Position
    Public Property X As Integer
    Public Property Y As Integer
End Class
Module PositionTextFixture
    Sub Main()
        Dim position1 As Position = New Position
        Console.WriteLine(position1.X = 0)
        Console.WriteLine(position1.Y = 0)
        '
        position1.X = 5
        Console.WriteLine(position1.X = 5)
        Console.WriteLine(position1.Y = 0)
        '
        position1.Y = 10
        Console.WriteLine(position1.X = 5)
        Console.WriteLine(position1.Y = 10)
        '
        Console.ReadLine()
    End Sub
End Module
Console Application Output
True
True
True
True
True
True
Visual Basic 2012 Broncode - Codevoorbeeld 244
Class Robot
    Private _Position As Position = New Position
    Public ReadOnly Property Position() As Position
        Get
            Position = _Position
        End Get
    End Property
    Private _Direction As Integer
    Public Sub Rotate()
        _Direction += 1
        If _Direction > 3 Then _Direction = 0
    End Sub
    Public Sub PlaceStep()
        Select Case _Direction
            Case 0 ' up
                Position.Y = Position.Y + 1
            Case 1 ' right
                Position.X = Position.X + 1
            Case 2 ' down
                Position.Y = Position.Y - 1
            Case 3 ' left
                Position.X = Position.X - 1
        End Select
    End Sub
End Class
Module RobotTestFixture
    Public Sub Main()
        Dim robot1 As Robot = New Robot
        Console.WriteLine(robot1.Position IsNot Nothing)
        Console.WriteLine(robot1.Position.X = 0)
        Console.WriteLine(robot1.Position.Y = 0)
        '
        robot1.PlaceStep()
        Console.WriteLine(robot1.Position IsNot Nothing)
        Console.WriteLine(robot1.Position.X = 0)
        Console.WriteLine(robot1.Position.Y = 1)
        '
        robot1.PlaceStep()
        Console.WriteLine(robot1.Position IsNot Nothing)
        Console.WriteLine(robot1.Position.X = 0)
        Console.WriteLine(robot1.Position.Y = 2)
        '
        robot1.Rotate()
        Console.WriteLine(robot1.Position IsNot Nothing)
        Console.WriteLine(robot1.Position.X = 0)
        Console.WriteLine(robot1.Position.Y = 2)
        '
        robot1.PlaceStep()
        Console.WriteLine(robot1.Position IsNot Nothing)
        Console.WriteLine(robot1.Position.X = 1)
        Console.WriteLine(robot1.Position.Y = 2)
        '
        robot1.Rotate()
        robot1.PlaceStep()
        Console.WriteLine(robot1.Position IsNot Nothing)
        Console.WriteLine(robot1.Position.X = 1)
        Console.WriteLine(robot1.Position.Y = 1)
        '
        robot1.Rotate()
        robot1.PlaceStep()
        Console.WriteLine(robot1.Position IsNot Nothing)
        Console.WriteLine(robot1.Position.X = 0)
        Console.WriteLine(robot1.Position.Y = 1)
        '
        robot1.Rotate()
        robot1.PlaceStep()
        Console.WriteLine(robot1.Position IsNot Nothing)
        Console.WriteLine(robot1.Position.X = 0)
        Console.WriteLine(robot1.Position.Y = 2)
        '
        Console.ReadLine()
    End Sub
End Module
Console Application Output
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
Hier werd ervoor ge-opteerd om een Robot zelf een Position object te laten creëren.  Dit omdat elk Robot object intensief gebruik maakt van zijn containde Position object.

De eigenschap Position in Robot is readonly gemaakt, het is immers mogelijk om via de commands Rotate en PlaceStep de toestand van het containde Position object te gaan manipuleren.
Opgave 2 :
Creëer een klasse waarvan objecten een voorstelling zijn van een punt op een XY-assenstelsel.  Een punt heeft als eigenschappen een X en Y positie.

Creëer ook een klasse waarvan objecten een voorstelling zijn van een lijn, met een start- en eindpunt.  Van de lijn moet je de lengte kunnen opvragen.
Oplossing 2 :
Visual Basic 2012 Broncode - Codevoorbeeld 245
Module PointAndLineTestFixtures
    Sub Main()
        PointTestFixture()
        LineTextFixture()
        '
        Console.ReadLine()
    End Sub
    Sub PointTestFixture()
        Dim point1 As Point = New Point
        Console.WriteLine(point1.X = 0)
        Console.WriteLine(point1.Y = 0)
        '
        point1.X = 1
        Console.WriteLine(point1.X = 1)
        Console.WriteLine(point1.Y = 0)
        '
        point1.Y = 3
        Console.WriteLine(point1.X = 1)
        Console.WriteLine(point1.Y = 3)
    End Sub
    Sub LineTextFixture()
        Dim line1 As Line = New Line
        Console.WriteLine(line1.StartPoint Is Nothing)
        Console.WriteLine(line1.EndPoint Is Nothing)
        Console.WriteLine(line1.Length = 0)
        '
        Dim startPoint As Point = New Point With {.X = 1, .Y = 4}
        line1.StartPoint = startPoint
        Console.WriteLine(line1.StartPoint Is startPoint)
        Console.WriteLine(line1.EndPoint Is Nothing)
        Console.WriteLine(line1.Length = 0)
        '
        Dim endPoint As Point = New Point With {.X = 5, .Y = 1}
        line1.EndPoint = endPoint
        Console.WriteLine(line1.StartPoint Is startPoint)
        Console.WriteLine(line1.EndPoint Is endPoint)
        Console.WriteLine(line1.Length = 5)
    End Sub
End Module
Class Point
    Public Property X As Integer
    Public Property Y As Integer
End Class
Class Line
    Public Property StartPoint As Point
    Public Property EndPoint As Point
    Public ReadOnly Property Length() As Double
        Get
            If StartPoint IsNot Nothing AndAlso EndPoint IsNot Nothing Then
                Dim side1 As Integer = Math.Abs(StartPoint.X - EndPoint.X)
                Dim side2 As Integer = Math.Abs(StartPoint.Y - EndPoint.Y)
                Length = Math.Sqrt(Math.Pow(side1, 2) + Math.Pow(side2, 2))
            End If
        End Get
    End Property
End Class
Console Application Output
True
True
True
True
True
True
True
True
True
True
True
True
True
True
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.