Visual Basic 2005 Coach



Dovnload 477.64 Kb.
Pagina12/13
Datum20.08.2016
Grootte477.64 Kb.
1   ...   5   6   7   8   9   10   11   12   13

9.2. Partiële klassen

Vaak worden klassen vrij uitgebreid en wordt het beheer ervan in teams een lastige taak vermits maar één iemand tegelijkertijd aan één bestand kan werken. Daarom lijkt het nuttig de definitie van een klasse te kunnen spreiden over meerdere bestanden. Om dit mogelijk te maken werden partial classes ingevoerd in .NET 2.0. Een voorbeeldje:


MyPartialClass01.vb
Public Class PartialDemo

Sub ProcedureA()


End Sub

End Class


MyPartialClass02.vb
Partial Public Class PartialDemo

Sub ProcedureA(ByVal s As String)


End Sub
Sub ProcedureB()
End Sub

End Class


MyPartialClass03.vb
Partial Public Class PartialDemo

Sub ProcedureC()


End Sub

End Class


Voor de gebruiker van de klasse blijft alles compleet transparant:

Eén van de plaatsen waar partiële klassen gebruikt worden in het .NET Framework 2.0 en Visual Studio 2005 is bij de definitie van Windows Forms formulieren. Voor de komst van partiële klassen (en dus voor Visual Studio 2005) vond u in het .vb-codebestand van een Windows Forms formulier een “Windows Form Designer generated code” sectie terug. Hierin worden de controls op het formulier geïnstantieerd en de nodige properties ingesteld om het formulier de look-and-feel te geven die u gedefinieerd hebt met de designer:

In Visual Studio 2005 wordt deze code verbannen naar een verborgen achterliggend bestand dat door middel van een partiële klassedefinitie samengevoegd wordt met uw code en dus als één geheel wordt gecompileerd:
Form1.vb
Public Class Form1

'Event handlers


Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As …
End Sub

'Eigen code

End Class
Form1.Designer.vb

Partial Class Form1

Inherits System.Windows.Forms.Form

'Gegenereerde code

End Class

Noot: In de toekomst – met de komst van Windows Presentation Foundation – zal de “Designer generated code” vervangen worden door een XML-definitie van de grafische interface, genaamd XAML (eXtensible Application Markup Language) die wordt omgezet naar een partiële klassedefinitie op de achtergrond.

9.3. Nullable types



Nullable types – waarvoor een vertalig zoals “mogelijk niets zijnde types” eerder belachelijke vormen aanneemt – maken de afgrond tussen waardetypes en referentietypes een stukje kleiner. Laten we dit even concretiseren.
In het gros van de hedendaagse toepassingen werkt u met gegevens uit een databank. Dergelijke gegevens hebben ongetwijfeld een type, zoals een string of een integer, maar hebben ook de extra eigenschap dat ze mogelijks “niet gedefinieerd” of null zijn, simpelweg omdat ze niet verplicht en dus niet opgegeven zijn. In het .NET Framework is er echter geen notie van nullable types als het aankomt op waardetypes. Zo kan je wél schrijven:
Dim s As String = Nothing

Console.WriteLine(s) 'Print niks


vermits String een referentietype is in .NET. Zaken zoals Integer en Double daarentegen zijn waardetypes en hebben geen notie van Nothing. Volgende code is dan ook weinig zinvol:
Dim i As Integer = Nothing

Console.WriteLine(i) 'Print 0


aangezien we geen onderscheid meer kunnen maken tussen een Integer die 0 is of die Nothing is, wat in termen van databases een hemelsbreed verschil vormt. Voor de komst van .NET 2.0 was de enige manier om hieraan het hoofd te bieden een conventie in te voeren en bijvoorbeeld te zeggen dat negatieve waarden Nothing voorstellen, uiteraard niet de meest robuuste aanpak, of een “inpaktype” te maken:
Public Class NullableInteger
Private _isNull As Boolean

Private _value As Integer


Public Sub New(ByVal value As Integer, ByVal isNull As Boolean)

_value = value

_isNull = isNull

End Sub
Public Property IsNull() As Boolean

Get

Return _isNull



End Get

Set(ByVal value As Boolean)

_isNull = value

End Set


End Property
Public Property Value() As Integer

Get


Return _value

End Get


Set(ByVal value As Integer)

_value = value

End Set

End Property


End Class
Niet meteen de mooiste oplossing en eerder onhandig in gebruik. Daarom voorziet .NET 2.0 in zogenaamde nullable types via volgende constructie:
Dim i As Nullable(Of Integer) = Nothing

Console.WriteLine(i) 'Print niks


i = 0

Console.WriteLine(i) 'Print 0


Handige properties van een nullable type (dat via generics is geïmplementeerd) zijn HasValue en Value. In C# bestaat er zelfs een speciale syntax om nullable types te declareren:
int i = 0; //niet nullable

int? j = null; //wel nullable

j = 1;
Nullable types zijn dus vooral handig om te werken met mogelijk ongedefinieerde data.

9.4. Operator overloading en indexers

In sommige gevallen bouwt u klassen die van nature bepaalde operatoren dienen te ondersteunen. Voorbeelden zijn klassen voor monetaire waarden (Euro, Dollar) en klassen die wiskundige begrippen voorstellen (Vector). In het verleden zou een Vector klasse in Visual Basic er als volgt kunnen uitgezien hebben:


Public Class Vector

Private _x, _y, _z As Double


Public Sub New(ByVal x As Double, ByVal y As Double, ByVal z As Double)

_x = x


_y = y

_z = z


End Sub
Public Property X() As Double

Get


Return _x

End Get


Set(ByVal value As Double)

_x = value

End Set

End Property


Public Property Y() As Double

Get


Return _y

End Get


Set(ByVal value As Double)

_y = value

End Set

End Property


Public Property Z() As Double

Get


Return _z

End Get


Set(ByVal value As Double)

_z = value

End Set

End Property


Public Function Add(ByVal v As Vector) As Vector

Return New Vector(v._x + _x, v._y + _y, v._z + _z)

End Function
Public Function Subtract(ByVal v As Vector) As Vector

Return New Vector(v._x - _x, v._y - _y, v._z - _z)

End Function
Public Function DotProduct(ByVal v As Vector) As Double

Return v._x * _x + v._y * _y + v._z * _z

End Function
Public Function CrossProduct(ByVal v As Vector) As Vector

Return New Vector(_y * v._z - Z * v._y, _z * v._x - _x * v._z, _x * v._y - _y * v._x)

End Function
Public Function Divide(ByVal d As Double) As Vector

Return New Vector(_x / d, _y / d, _z / d)

End Function
Public Function Norm() As Double

Return Math.Sqrt(_x * _x + _y * _y + _z * _z)

End Function
Public Overrides Function ToString() As String

Return String.Format("({0},{1},{2})", _x, _y, _z)

End Function

End Class


Het gebruik wordt dan echter niet meteen zeer intuïtief, of op zijn minst eerder omslachtig:
Dim v1 As New Vector(1, 2, 3)

Dim v2 As New Vector(9, 8, 7)


Console.WriteLine("v1 : {0}", v1)

Console.WriteLine("v2 : {0}", v2)

Console.WriteLine("||v1|| : {0}", v1.Norm())

Console.WriteLine("v1/||v1|| : {0}", v1.Divide(v1.Norm()))

Console.WriteLine("v1 x v2 : {0}", v1.CrossProduct(v2))

Console.WriteLine("v1 . v2 : {0}", v1.DotProduct(v2))

Console.WriteLine("v1 - v2 : {0}", v1.Subtract(v2))

Console.WriteLine("v1 + v2 : {0}", v1.Add(v2))


Via operator overloading wordt het mogelijk iets dergelijks te schrijven:
Dim v1 As New Vector(1, 2, 3)

Dim v2 As New Vector(9, 8, 7)


Console.WriteLine("v1 : {0}", v1)

Console.WriteLine("v2 : {0}", v2)

Console.WriteLine("||v1|| : {0}", v1.Norm())

Console.WriteLine("v1/||v1|| : {0}", v1 / v1.Norm())

Console.WriteLine("v1 x v2 : {0}", v1 * v2)

Console.WriteLine("v1 . v2 : {0}", v1.DotProduct(v2))

Console.WriteLine("v1 - v2 : {0}", v1 - v2)

Console.WriteLine("v1 + v2 : {0}", v1 + v2)


Hiertoe dient u volgende members aan de klasse Vector toe te voegen:
Public Shared Operator +(ByVal v1 As Vector, ByVal v2 As Vector) As Vector

Return v1.Add(v2)

End Operator
Public Shared Operator -(ByVal v1 As Vector, ByVal v2 As Vector) As Vector

Return v1.Subtract(v2)

End Operator
Public Shared Operator -(ByVal v As Vector) As Vector

Return New Vector(-v._x, -v._y, -v._z)

End Operator
Public Shared Operator *(ByVal v1 As Vector, ByVal v2 As Vector) As Vector

Return v1.CrossProduct(v2)

End Operator
Public Shared Operator /(ByVal v As Vector, ByVal d As Double) As Vector

Return v.Divide(d)

End Operator
Merk op dat we maar één *-operator kunnen definiëren en dus een DotProduct procedure nodig blijft. Verder is in bovenstaande code ook de unaire negatieoperator toegevoegd (3e operatordefinitie). Alle operator overloads zijn statische methoden. Tot slot is het belangrijk op te merken dat operator overloading niet door elke taal ondersteund wordt en het dus nodig blijft ook methoden met eenzelfde gedrag toe te voegen. In ons geval hebben we de klasse gewoon uitgebreid met operator overloads terwijl we de bestaande functionaliteit behouden.
Naast operator overloading is het gebruik van indexers ook interessant om de klasse een intuïtiever karakter te geven. Voor een vector zijn wiskundigen vaak geneigd zaken te schrijven zoals v0 of vx om de x-coördinaat van een vector aan te duiden. Via een indexer wordt iets dergelijks min of meer mogelijk gemaakt, zij het dan wel met een notatie met haakjes in plaats van “subscript”:
Dim v1 As New Vector(1, 2, 3)

Console.WriteLine("v1 = ({0},{1},{2})", v1(0), v1("y"), v1.Z)


Om dit te ondersteunen dient u volgende code voor een default property aan de klasse Vector toe te voegen:
Default Public Property Vector(ByVal index As Integer) As Double

Get


Select Case index

Case 0


Return _x

Case 1


Return _y

Case 2


Return _z

End Select

End Get

Set(ByVal value As Double)



Select Case index

Case 0


_x = value

Case 1


_y = value

Case 2


_z = value

End Select

End Set

End Property


Default Public Property Vector(ByVal index As String) As Double

Get


Select Case index.ToLower()

Case "0", "x"

Return _x

Case "1", "y"

Return _y

Case "2", "z"

Return _z

End Select

End Get

Set(ByVal value As Double)



Select Case index.ToLower()

Case "0", "x"

_x = value

Case "1", "y"

_y = value

Case "2", "z"

_z = value

End Select

End Set

End Property


Noot: Gebruik operator overloading en indexers enkel als ze bijdragen tot een verhoogd gebruiksgemak en een niet-dubieus karakter aannemen. Anders loopt u het risico om uit te komen op een constructie die nog moeilijker te begrijpen is dan voorheen. Vanuit het perspectief van versionering dient men zich er ook van bewust te zijn dat het introduceren van operator overloads en indexers irreversibel is. Eens toegevoegd kan men zich niet permitteren deze terug te verwijderen aangezien dit zou leiden tot het breken van bestaande code die ervan gebruik maakt.



1   ...   5   6   7   8   9   10   11   12   13


De database wordt beschermd door het auteursrecht ©opleid.info 2017
stuur bericht

    Hoofdpagina