P
'
t
i
t
e
C
h
a
t
t
e
 
spacer~ THE CODE THAT IS THE HARDEST TO DEBUG IS THE CODE THAT YOU KNOW CANNOT POSSIBLY BE WRONG Articles | Connexion
 
~Créer une collection en VB

Précédent  
  Visual Basic  
  Suivant
 Présentation

Les collections d'objets sont extrêmement utile en programmation. Contrairement à Java, l'offre de Visual Basic en terme de collections est pauvre. On en dénombre deux: Collection et PropertyBag. Nous allons commencer par voir quels problèmes posent l'objet Collection avant d'en créer une variante : Vector.

AVANT PROPOS : Les algorithmes utilisés pour nos implémentations ne sont pas efficaces du tout. Cependant ils permettent d'illustrer simplement la création de collections.
 Sommaire


 L'objet Collection

L'objet Collection est un objet permettant de stocker un ensemble de données dans un tableau extensible. Sans connaître par avance le nombre d'éléments que nous souhaitons ajouter au tableau, nous pouvons quand même les y placer sans se soucier d'un problème de limite. Les éléments sont donc indexés dans le tableau. On peut donc les lire de manière classique. Mais cette collection offre une fonctionnalité supplémentaire: l'indexation par clé. Vous pouvez par exemple associer l'objet "La plus jolie" à la clé "Claire".

Malgré ces qualités apparentes, l'objet Collection est un monstre. Premièrement à cause de sa fâcheuse tendance à générer des erreurs et deuxièment à cause de sa structure logique affreuse. L'objet Collection est un mélange bâtard d'un vecteur et d'une table de hachage. De plus les fonctions d'insertion d'éléments se confondent avec la méthode d'ajout.

Voici un exemple d'utilisation de cet objet:

' nouvelle collection
Dim c As New Collection

' on ajoute un élément avec clé
Call c.Add("La plus jolie", "Claire")
' lecture par clé
MsgBox c.Item("Claire")
' lecture par index
MsgBox c.Item(1)
       
      
JextCopier dans Jext | Jext | Plugin Codegeek
Dans cet exemple, nous ajoutons simplement un élément en lui donnant une clé. Si vous exécutez ce programme, vous verrez que la lecture par clé et par index retournent le même message. Bien entendu, si nous n'avions pas spécifié de clé pour l'objet, la première lecture ne marcherait pas:

' nouvelle collection
Dim c As New Collection

' on ajoute un élément avec clé
Call c.Add("La plus jolie")
' lecture par clé
MsgBox c.Item("Claire")
' ERREUR
       
      
JextCopier dans Jext
Ce programme génère une erreur lors de l'exécution. Et ceci est un des problèmes majeurs de l'objet Collection. Toute tentative de lecture infructeuse se solde par une erreur. Ceci rend votre code beaucoup plus comple en vous astreignant à gérer des erreurs supplémentaires.

Mais ceci n'est pas le seul problème. Si, par exemple, vous voulez insérer un élément dans la collection, vous devrez également passer par la méthode Add().

Dim c As New Collection
Call c.Add("La plus jolie", "Claire")
' insertion AVANT le premier élément
Call c.Add("Jeff Trent", , "Claire")
MsgBox c.Item("Claire")
' affiche "Jeff Trent" et non "La plus joli"
MsgBox c.Item(1)
       
      
JextCopier dans Jext
La métode Add() permet en effet d'ajouter un élément, avec ou sans clé, avant ou après un autre élément. L'élément de référence peut être désigné par son index ou sa clé. Néanmoins, cette possibilité ne complique que d'avantage la syntaxe de la méthode Add(). En outre, une méthode nommée Insert() serait bien plus intuitive.

Pour pallier à ces limitations nous allons créer notre propre implémentation de cet objet. Ne souhaitant pas faire l'amalgame entre un tableau dynamique et un tableau d'indexation par clés, nous allons créer deux objets:
  • Vector, qui est un tableau dynamique
  • HashMap, qui est un tableau d'indexation par clés, faisant appel à Vector


 L'objet Vector

La création d'un tableau à redimensionnement automatique est chose facile en Visual Basic. Ce langage propose en effet une instruction nommée ReDim permettant de changer la taille d'un tableau. Prenons cet exemple:

' tableau
Dim m() As Integer
' contient 10 entiers
ReDim m(1 To 10)
m(1) = 666

' redimensionnement
ReDim m(1 To 15)
MsgBox UBound(m)
MsgBox m(1)
       
      
JextCopier dans Jext | Jext | Plugin Codegeek
Ce code commence par créer un tableau de 10 entiers auquel on affecte une valeur. Ce tableau est ensuite redimensionné pour contenir 15 éléments. Malheureusement, la valeur que nous avions placé à l'index 1 a disparue. Il faut pour cela employer l'instruction optionelle Preserve. Notez que l'instruction ReDim ne peut pas fonctionner sur un tableau dont les dimensions sont précisées dans la déclaration Dim.

Dim m() As Integer
ReDim m(1 To 10)
m(1) = 666

' redimensionnement
' en préservant les valeurs
ReDim Preserve m(1 To 15)
MsgBox m(1)
       
      
JextCopier dans Jext
Dans ce second cas, la valeur 666 est bien préservée dans le tableau.

L'instruction ReDim sera utilisée chaque fois que nous aurons à redimensionner le tableau. Ceci arrivera en plusieurs occasions. Notre objet possède deux propriétés: sa taille et sa capacité. La première propriété indique le nombre d'éléments effectivement disponibles dans le tableau. La propriété de capacité indique le nombre d'éléments que la collection peut encore accueillir avant redimension. Lorsque la taille devient égale à la capacité, nous devons augmenter la taille du tableau. Par convention nous doublerons cette taille.

Voici la liste exhaustive des fonctions que nous allons implémenter dans notre objet Vector:
  • addElement, ajoute un élément à la collection
  • clear, efface le contenu de la collection
  • contains, retourne vrai si la collection contient l'élément spécifié
  • getCapacity, renvoie la capacité actuelle de la collection
  • getElementAt, lit l'élément à la position spécifiée
  • getSize, renvoie le nombre d'éléments de la collection
  • indexOf, donne la position d'un élément au sein de la collection
  • insertElementAt, insère un élément
  • isEmpty, vrai si la taille est égale à 0
  • lastIndexOf, dernière position d'un élément de la collection
  • removeElement, enlève la première occurence de l'élément de la collection
  • removeElementAt, enlève l'élément occupant la position donnée
  • setCapacity, change la capacité totale
  • setElementAt, modifie la valeur d'un élément
  • setSize, change la taille
  • trimToSize, ramène la capacité de la collection à sa taille

Comme vous le voyez notre objet Vector est particulièrement riche en possibilités. Son utilisation est plus claire que celle de Collection puisque ses nombreuses méthodes et fonctions ne jouent qu'un seul et unique rôle à la fois. Le code source complet de notre nouvel objet est téléchargeable à la fin de ce cours.


 L'objet HashMap

Notre objet Vector possède une seule défficience en regard de Collection. Nous allons y remédier tout de suite. Nous n'aurons besoin que de quelques méthodes seulement. Une méthode put() pour ajouter un élément avec sa clé et une méthode get() pour lire un élément. Nous ajouterons également deux fonctions permettant de récupérer d'une part la liste des clés et d'autre part la liste des éléments.

Voici le code source complet de notre objet. L'utilisation de Vector en rend la programmation très très simple:

' keys
Private keys   As Vector
' datas
Private values As Vector

' création des vecteurs
Private Sub Class_Initialize()
    Set keys = New Vector
    Set values = New Vector
End Sub

' retourne un élément via sa clé
Public Function getElement(key As Variant) As Variant
    Dim i%
    i = keys.indexOf(key)
    If i <> -1 Then
        getElement = values.getElementAt(i)
    Else
        getElement = Empty
    End If
End Function

' retourne la liste des clés
Public Function getKeys() As Vector
    Set getKeys = keys
End Function

' retourne la liste des valeurs
Public Function getValues() As Vector
    Set getValues = values
End Function

' ajoute un élément indexé par une clé
Public Sub putElement(ByVal obj As Variant, ByVal key As Variant)
    Call keys.addElement(key)
    Call values.addElement(obj)
End Sub
       
      
JextCopier dans Jext | Jext | Plugin Codegeek
Nanti de ce nouvel objet, nous allons recréer le premier exemple de ce cours:

' nouvelle collection
Dim h As New HashMap

' on ajoute un élément avec clé
Call h.putElement("La plus jolie", "Claire")
' lecture par clé
MsgBox h.getElement("Claire")
' lecture par index
MsgBox h.getValues().getElementAt(0)
       
      
JextCopier dans Jext
Et ça marche parfaitement ! Notez simplement que l'indexation des valeurs dans le tableau commence à zéro (comme en C). Notre objet HashMap a encore besoin d'une fonction permettant de retirer un élément (la clé devra être enlevée aussi). Mais ceci devra être réalisé par vos soins. La structure de nos nouveaux objets est bien plus lisible et logique que celle de la Collection proposée par Visual Basic. L'objet PropertyBag évoqué en introduction devient également caduque par l'introduction de HashMap.


 Téléchargements

Voici quelques fichiers à télécharger:
  • article1.zip, le code source des objets Vector et HashMap
  • Syxigh, code source d'un logiciel faisant une utilisation intensive de nos deux objets



par Romain Guy
romain.guy@jext.org
http://www.jext.org
Dernière mise à jour : 14/10/2006


Précédent  
  Visual Basic  
  Suivant

 
#ProgX©2005 Mathieu GINOD - Romain GUY - Erik LOUISE