Buchempfehlung
Windows System Programming
Windows System Programming
Das Kompendium liefert viele interessante Informationen zur Windows-Programmierung auf Englisch. [Mehr Infos...]
FreeBASIC-Chat
Es sind Benutzer im FreeBASIC-Chat online.
(Stand:  )
FreeBASIC bei Twitter
Twitter FreeBASIC-Nachrichten jetzt auch über Twitter erhalten. Follow us!

Code-Beispiel

Code-Beispiele » Objektorientierung

Zugriffskontrolle über Properties

Lizenz:Erster Autor:Letzte Bearbeitung:
FBPSLRedakteurnemored 09.09.2012

Der folgende Code verwaltet eine BefehlsreferenzeintragZSTRING-Liste mit Properties. Der Benutzer hat keine Möglichkeit, direkt auf die Listeneinträge zuzugreifen:

Type MyList
   ' hier gilt noch PUBLIC:
   Declare Constructor ()        ' wird automatisch bei Erstellung aufgerufen
   Declare Destructor  ()        ' wird automatisch bei Beendigung aufgerufen

   Private:                      ' Nur interne Verwendung
      count    As Integer           ' Anzahl der Listenelemente
      adresses As Integer Ptr       ' Pointer auf ein Datenfeld; jedes Element des Feldes zeigt auf einen ZSTRING
      strings  As ZString Ptr       ' Hilfs-Pointer, zum leichteren Umgang mit den ZSTRINGs

   Public:                       ' Für den User
      ' Eigenschaften
      Declare Property Items  (index As Integer)       As String     ' Listenelement Nr. 'index' ausgeben
      Declare Property Items  (index As Integer, value As String)    ' Wert v. Listenelement Nr. 'index' setzen

      ' Methoden
      Declare Sub      AddItem(index As Integer, value As String)    ' Neues Element zur Liste hinzufügen
      Declare Sub      DelItem(index As Integer)                     ' Element Nr. 'index' aus Liste löschen
      Declare Function ItemCount()                     As Integer    ' Anzahl der Listenelemente ausgeben
End Type
'================================================='
Dim As MyList Liste
Dim As Integer i

Liste.Items  (1) = "nein"
Liste.AddItem 2,   "abbrechen"
Liste.AddItem 1,   "ja"
Liste.AddItem 2,   "delete me"

For i = 1 To Liste.ItemCount
   print i, Liste.Items(i)
Next
print

Liste.DelItem 2

For i = 1 To Liste.ItemCount
   print i, Liste.Items(i)
Next

Sleep
'================================================='
Constructor MyList ()
   This.count       = 1
   This.adresses    = CAllocate(1)
   This.strings     = CAllocate( Len("") )
   This.adresses[0] = Cast( Integer, This.strings )
End Constructor
'..............................................................................'
Destructor MyList ()
   Dim As Integer i

   With This
      For i = 1 To .Count
         .Strings = Cast( ZString Ptr, .adresses[i - 1] )
         DeAllocate .Strings
      Next

      DeAllocate .adresses
   End With
End Destructor
'-------------------------------------------------------'
Property MyList.Items(index As Integer) As String
   If (index < 1) Or (index > This.Count) Then Return ""          ' Überprüfe, ob Listenindex existiert;
                                                                  ' Wenn nein, beende Prozedur

   This.Strings = Cast( ZString Ptr, This.adresses[index - 1] )   ' Finde richtige Adresse des Strings
   Return *This.Strings                                           ' Gib gewünschten String zurück
End Property
'..............................................................................'
Property MyList.Items(index As Integer, value As String)
   Dim As Integer i
   Dim As ZString Ptr tmp

   With This
      If (index < 1) Or (index > .Count) Then Return        ' Überprüfe, ob Listenindex existiert;
                                                            ' Wenn nein, beende Prozedur

      .Strings = Cast( ZString Ptr, .adresses[index - 1] )  ' Finde richtige Adresse des Strings
      tmp = ReAllocate( .Strings, Len(value) + 1)           ' Reserviere Speicherplatz für neuen String
      If tmp Then .Strings = tmp Else Return                ' Fahre nur fort, wenn Reservierung erfolgreich

      .adresses[index - 1] = Cast( Integer, .Strings )      ' Speichere neue Adresse

      For i = 0 To Len(value) - 1                           ' Kopiere neuen String in neue Speicherstelle
         .Strings[i] = value[i]
      Next
      .Strings[ Len(value) ] = 0                            ' Setze letztes Element auf 0, da es ein ZSTRING ist

   End With
End Property
'::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::'
Sub MyList.AddItem(index As Integer, value As String)
   Dim As Integer i
   Dim As Integer Ptr tmp

   With This
      If (index < 1) Or (index > .Count + 1) Then Return    ' Überprüfe, ob Listenindex existiert;
                                                            ' Wenn nein, beende Prozedur

      tmp = ReAllocate(.adresses, .Count + 1)               ' reserviere Speicher für eine neue Adresse
      If tmp Then .adresses = tmp Else Return               ' Fahre nur fort, wenn Reservierung erfolgreich

      For i = .Count - 1 To index - 1 Step - 1              ' Verschiebe bisher gespeicherte Adressen i.d. Adress-
         .adresses[i + 1] = .adresses[i]                    ' liste um eins nach vorne, um Platz für das neue
      Next                                                  ' Element zu schaffen
      .count += 1                                           ' Erhöhe den Element-Zähler um eins

      .Strings = Allocate( Len(value) + 1 )                 ' Reserviere Speicherplatz für neuen String

      For i = 0 To Len(value) - 1                           ' Kopiere neuen String in neue Speicherstelle
         .Strings[i] = value[i]
      Next
      .Strings[ Len(value) ] = 0                            ' Setze letztes Element auf 0, da es ein ZSTRING ist

      .adresses[index - 1] = Cast( Integer, .Strings )      ' Speichere die Adresse des neuen Elements
   End With
End Sub
'..............................................................................'
Sub MyList.DelItem(index As Integer)
   Dim As Integer i
   Dim As Integer Ptr tmp

   With This
      If (index < 1) Or (index > .Count) Then Return        ' Überprüfe, ob Listenindex existiert;
                                                            ' Wenn nein, beende Prozedur

      .Strings = Cast( ZString Ptr, .adresses[index - 1] )  ' Lösche den String aus dem Speicher
      DeAllocate .Strings

      tmp = Allocate(.Count - 1)                            ' Erstelle temporäre Kopie der Adress-Liste ohne zu
      For i = 0 To .Count - 1                               ' löschendes Element
         If     i  < index - 1 Then
            tmp[i] = .adresses[i]
         ElseIf i  = index - 1 Then
            ' keine Aktion, da Element gelöscht werden soll!
         Else
            tmp[i - 1] = .adresses[i]
         End If
      Next

      Count -= 1                                            ' aktualisiere Zähler
      DeAllocate .adresses                                  ' Entferne alte Adressliste
      .adresses = tmp                                       ' Übernehme neue Adressliste
   End With
End Sub
'..............................................................................'
Function MyList.ItemCount() As Integer
   Return This.Count
End Function

Ausgabe:

1   ja
2   delete me
3   nein
4   abbrechen

1   ja
2   nein
3   abbrechen

Dieses Beispiel verdeutlicht die Vorteile der PROPERTY-Methode: Zwar ist der Aufwand auf den ersten Blick etwas höher; für jeden denkbaren Zugriff ist eine eigene Prozedur von Nöten. Allerdings kann hierbei gleich festgelegt werden, ob der Zugriff im Lese- und/oder Schreibmodus erfolgen darf; hier z. B. kann jederzeit die Anzahl der Elemente in der Liste abgefragt werden, jedoch kann der Wert nur über .AddItem und .DelItem geändert werden. Außerdem kann automatisch überprüft werden, ob die angegebenen Parameter überhaupt zulässig sind; hier z. B. wird in jeder Property (mit Ausnahme von .ItemCount, das ja keine Parameter besitzt) geprüft, ob sich 'index' im zulässigen Bereich befindet.
Dank der Möglichkeit, einen BefehlsreferenzeintragCONSTRUCTOR zu verwenden, wird die Liste automatisch voll funktionsfähig initiiert, und der BefehlsreferenzeintragDESTRUCTOR sorgt dafür, dass keine Reste im Speicher zurück bleiben.
Und nicht zuletzt ist der Einsatz der erstellten Eigenschaften und Methoden im Modullevel denkbar einfach. Bedenken Sie den Aufwand, dessen es bedarf, um in ein BefehlsreferenzeintragSTRING-BefehlsreferenzeintragArray ein Element an beliebiger Stelle einzufügen. Und dabei kann immer noch ein Fehler unterlaufen, wenn Indizes außerhalb des zulässigen Bereichs angegeben werden.


Zusätzliche Informationen und Funktionen
  • Das Code-Beispiel wurde am 09.09.2012 von Redakteurnemored angelegt.
  • Die aktuellste Version wurde am 09.09.2012 von Redakteurnemored gespeichert.
  Bearbeiten Bearbeiten  

  Versionen Versionen