Apprenez à programmer en VB .NET
Last updated on Monday, June 24, 2013
  • 4 semaines
  • Facile

Free online content available in this course.

Paperback available in this course

eBook available in this course.

Got it!

Concepts avancés

La POO est un monde fabuleux, pour le moment elle doit vous sembler un peu trouble, mais avec un peu de pratique vous n'allez plus pouvoir vous en passer. Mais en attendant que tout ça devienne limpide, je vais vous apporter quelques nouvelles notions afin de vous permettre d'employer au mieux ces nouvelles connaissances.

Dans ce chapitre nous allons aborder quelques notions plus poussées et utiles. Au menu : l'héritage, les classes abstraites, les événements, la surcharge d'opérateurs, les propriétés par défaut, les collections, les bibliothèques de classes et comment les utiliser. Soyons fous !

Bon appétit ! :)

L'héritage

Premier concept important : l'héritage. J'ai déjà tenté de vous exposer cette notion dans la partie sur les fenêtres, mais ce n'était pas très judicieux, vous ne connaissiez pas la POO. On va donc tout recommencer ici.

Bon, j'espère que les principes de création de classe et de programmation orientée objet sont acquis. Je sais que c'est une rude partie, mais allez chercher un café et reprenez tout ça calmement.

Vous connaissez tous les mots français « héritage » et « hériter ». Wikipédia nous donne la définition suivante : « devenir propriétaire d’une chose par droit de succession ». Eh bien ce concept est quasiment le même en programmation, à une petite nuance près. Dans la vraie vie un héritage transmet simplement une chose, en programmation l'héritage d'une classe va dupliquer cette dernière et donner ses caractéristiques à la classe qui hérite.

Regardez la figure suivante.

Une classe Piano et une classe Guitare
Une classe Piano et une classe Guitare

Admettons que je veuille créer deux classes comme celles-là. Une classe Guitare et une classe Piano. Vous remarquez qu'elles présentent des similitudes, elles possèdent toutes les deux un attribut Notes qui va contenir le panel de notes que cet instrument peut jouer et un Sub Joue qui va lui permettre de produire un son.

En plus de ces deux éléments communs, elles présentent des particularités spécifiques à leur type : la guitare aura en plus le nombre de cordes qu'elle possède et une fonction permettant d'utiliser le vibrato. Le piano quand à lui, contiendra une variable comptant le nombre de touches qu'il possède et un Sub pour appuyer sur une touche spécifique.

Vous remarquez tout de suite que ces similitudes vont devoir être écrites en double. Beaucoup de travail et de lignes pour rien. C'est pour cela que les programmeurs ont introduit le concept de l'héritage.

Regardez, si nous créons une troisième classe nommée Instrument qui contient des choses communes à tous les instruments, comme l'attribut Notes par exemple, il serait simple d'inclure cette classe dans les autres, de façon à bénéficier de ses caractéristiques, comme le montre le schéma de la figure suivante.

La classe Instrument est incluse dans les autrs classes
La classe Instrument est incluse dans les autrs classes

C'est justement là toute la puissance de l'héritage. En une ligne de programmation nous allons pouvoir faire hériter nos classes Guitare et Piano de Instrument de façon à leur donner la possibilité d'utiliser ses membres.

Alors, qu'est-ce que cette modification implique concrètement pour nos classes ?

Eh bien d'un point de vue extérieur à la classe, une fois instanciée par exemple, c'est transparent. C'est-à-dire qu'on ne saura pas si le membre de la classe auquel on va accéder appartient à la classe mère ou fille.

En revanche, d'un point de vue interne à la classe, ça se complique. Nous allons devoir apprendre à jongler entre les membres appartenant à la classe fille ou à la classe mère au travers de préfixes (du même type que Me).

Ce mot est MyBase.

Dans le schéma visible à la figure suivante, on se place du point de vue de la classe fille. Si depuis cette classe fille on débute une ligne par Me., les membres auxquels nous pourrons accéder seront ceux de la classe fille et de toutes les classes dont elle hérite. En revanche, en utilisant MyBase. nous accèderons uniquement aux membres de la classe mère.

Choisissez bien entre Me et MyBase
Choisissez bien entre Me et MyBase

Cette information va nous être très précieuse, surtout lorsque nous allons faire appel à des classes héritées qui ont besoin d'être instanciées.

Vous avez deux choix possibles dans notre exemple : créer un constructeur dans Instrument ou non. Si vous décidez de ne pas en mettre, cette classe va être considérée comme abstraite (le chapitre d'après). En revanche, si vous décidez de mettre un constructeur, il va falloir instancier la classe mère au même moment que la classe fille.

Bon, arrêtons la théorie et attaquons tout de suite la pratique pour que vous puissiez voir concrètement à quoi ça ressemble.

Public Class Instrument

    Private _Notes() As Integer

    Sub New(ByVal Notes() as Integer)
        _Notes = Notes
    End Sub

End Class

Public Class Guitare
    Inherits Instrument 'Hérite d'Instrument
    
    Private _NbCordes As Integer

    Sub New(ByVal Notes() As Integer, ByVal NbCordes As Integer)
        MyBase.New(Notes) 'On instancie la mère
        _NbCordes  = NbCordes
    End Sub

End Class

Dans ce petit bout de code, j'ai créé deux classes : Instrument et Guitare.

La classe Instrument est la classe mère, elle a un attribut _Notes et un constructeur. La classe Guitare est la classe fille, elle a également un attribut _NbCordes et un constructeur.

La ligne Inherits Instrument indique que la classe hérite d'Instrument. Et lors de l'instanciation de la classe fille, le constructeur de la classe mère est lui aussi appelé via MyBase.New(Notes).

Les classes abstraites

Une classe abstraite est une classe ne pouvant pas être instanciée, autrement dit on ne peut pas créer d'objet à partir de ce moule.

Alors à quoi va-t-elle nous servir ?

Elle va permettre de créer des classes dérivées. En clair, cette classe va seulement servir de base (une classe mère) pour des classes qui vont en dériver. Comme notre exemple sur les instruments. Une guitare, un piano, bref des instruments concrets, nous allons les instancier et les utiliser. Cependant la classe Instrument, la classe mère de toutes les autres, nous aurions pu la définir en classe abstraite.

Donc notre précédent code va devenir :

Public MustInherit Class Instrument

    Private _Notes() As Integer

    Public Property Notes As Integer()
        Set(ByVal value() As Integer)
            _Notes = value
        End Set
        Get
            Return _Notes
        End Get
    End Property

End Class

Public Class Guitare
    Inherits Instrument 'Hérite d'Instrument

    Private _NbCordes As Integer

    Sub New(ByVal Notes() As Integer, ByVal NbCordes As Integer)
        MyBase.Notes = Notes 'On spécifie la propriété Notes de la mère
        _NbCordes = NbCordes
    End Sub

End Class

Vous voyez qu'ici le mot-clé MustInherit spécifié dans la déclaration de la classe (qui signifie en français « doit hériter », mais qu'il est mieux de traduire par « doit être hérité »), spécifie que cette classe sera abstraite, elle ne pourra pas être utilisée telle quelle.

Ma classe Guitare est donc ici pour hériter d'Instrument. Une fois la classe Guitare instanciée, on peut très bien accéder aux membres d'Instrument. La syntaxe MaGuitare.Notes(0) est tout à fait correcte (où MaGuitare est mon objet créé).

Il existe toutefois une seconde utilisation possible pour les classes abstraites ; en tant que bibliothèques de fonctions.

Plutôt que de placer toutes vos fonctions dans le fichier qui contient la fenêtre, il vous est possible de créer un fichier de classe, nommé « Fonctions » par exemple, et d'y inscrire des fonctions qui pourront être utilisées à partir de n'importe où dans votre programme.

Public Class Fonctions

    Shared Function Somme(ByVal X As Integer, ByVal y As Integer) As Integer
        Return X + y
    End Function

    Shared Function Difference(ByVal X As Integer, ByVal y As Integer) As Integer
        Return X - y
    End Function

End Class

Ma classe Fonctions, j'ai retiré le mot MustInherit.

Vous vous apercevez que mes fonctions ne sont pas publiques ou privées, mais Shared. Le mot-clé Shared, signifiant « partagé » en français, indique que cette fonction peut être utilisée sans avoir besoin d'instancier la classe. Autrement dit, dans le programme on pourra utiliser Fonctions.Addition(1,2) où l'on veut.

Les avantages : la possibilité de regrouper des fonctions utiles dans le même fichier. Les inconvénients : puisque la classe n'est pas instanciée, il n'est pas possible d'accéder à des membres externes à la fonction. Des variables globales ne pourront pas être utilisées par exemple.

Les événements

Vous vous souvenez des événements dans nos contrôles ? Eh bien ici c'est le même principe.

Un événement est une fonction appelée lorsque quelque chose se produit. Ce « quelque chose » peut être l'appui d'un clic sur un bouton, l'insertion de texte dans une textbox, le chargement d'une fenêtre, etc. Vous vous souvenez du mot-clé Handles ? C'est ce qui indique l'écoute d'un événement sur un objet. On avait l'habitude de l'utiliser pour des contrôles visuels, nous allons désormais apprendre à écouter un événement sur notre classe.

Pour commencer, il faut spécifier ce qui va déclencher l'événement à l'intérieur de notre classe.

Dans ma classe je déclare un timer en global avec WithEvents, ce qui signifie que je vais pouvoir écouter les événements de cet objet. Vous avez déjà utilisé un timer en tant que contrôle (les contrôles étant d'office avec WithEvents), cette fois il ne sera visible que côté code. Je l'instancie, puis le lance dans le constructeur avec une seconde en interval, j'utilise la fonction Start() pour le démarrer plutôt que Enable = true.

Dans l'événement Tick du timer, j'incrémente un compteur ; une fois arrivé à 10 je déclenche l'événement.

Ça donne le code suivant dans notre classe :

Private WithEvents _Tim As Timer
    Private _Compteur As Integer

    Sub New()
        _Tim = New Timer
        _Tim.Interval = 1000
        _Tim.Start()
        _Compteur = 0
    End Sub

    Public Event DixSecondes()

    Sub _Tim_Tick() Handles _Tim.Tick
        _Compteur += 1
        If _Compteur = 10 Then
            RaiseEvent DixSecondes()
        End If
    End Sub

Vous voyez pour commencer la déclaration des variables (compteur et timer). Puis le constructeur initialise, instancie et démarre tout ça. Vient l'événement Tick du timer, je compte et je déclenche l'événement avec le mot-clé RaiseEvent. L'événement déclenché doit être déclaré : Public Event DixSecondes(), en public pour pouvoir « l'écouter » de l'extérieur.

Allons du côté de notre fenêtre qui va instancier notre objet. La classe déclarée en globale doit être faite avec le mot-clé WithEvents également :

Dim WithEvents MaClasse1 As MaClasse

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        MaClasse1 = New MaClasse1()
    End Sub

    Sub AttendsLesDixSecondes() Handles MaClasse1.DixSecondes
        MsgBox("Dix secondes que l'objet est crée")
    End Sub

Puis je l'instancie dans le form.

Pour finir j'ai écouté l'événement avec Sub AttendsLesDixSecondes() Handles MaClasse1.DixSecondes. Lorsque les 10 secondes sont écoulées, je déclenche une MsgBox.

Avec des arguments

Et on peut passer des arguments avec nos événements. Côté classe on déclare l'événement avec :

Public Event DixSecondes(ByVal Message As String)

On voit qu'il attend un argument de type String.

Donc lorsqu’on va l'appeler :

RaiseEvent DixSecondes("Dix secondes que l'objet est crée")

… je lui passe mon argument. Et finalement côté fenêtre, le Handles de mon événement s'effectue ainsi :

Sub AttendsLesDixSecondes(ByVal Message As String) Handles MaClasse1.DixSecondes
        MsgBox(Message)
    End Sub

La surcharge

Même si vous ne savez pas ce que ce mot signifie, je peux vous dire que vous y avez déjà été confrontés. Souvenez-vous, lorsque vous passez des arguments à une fonction et que l'assistant de Visual Basic vous propose plusieurs possibilités pour passer ces arguments, comme à la figure suivante.

L'assistant de Visual Basic vous propose plusieurs possibilités
L'assistant de Visual Basic vous propose plusieurs possibilités

Vous voyez que l'infobulle spécifie « 2 sur 15 ». J'ai choisi la seconde possibilité, sur quinze possibles, de donner les arguments. C'est cela la surcharge, pour la même fonction, avoir plusieurs « résultats » possibles en fonction du passage des arguments.

Créons tout de suite un constructeur surchargé pour vous montrer ce que cela implique :

Public MustInherit Class Instrument

    Private _Notes() As Integer

    Public Property Notes As Integer()
        Set(ByVal value() As Integer)
            _Notes = value
        End Set
        Get
            Return _Notes
        End Get
    End Property

End Class

Public Class Guitare
    Inherits Instrument 'Hérite d'Instrument

    Private _NbCordes As Integer

    Sub New()
        _NbCordes = 0
    End Sub

    Sub New(ByVal Notes() As Integer)
        MyBase.Notes = Notes
        _NbCordes = 0
    End Sub

    Sub New(ByVal Notes() As Integer, ByVal NbCordes As Integer)
        MyBase.Notes = Notes
        _NbCordes = NbCordes
    End Sub

End Class

J'ai déclaré dans ma classe Guitare trois constructeurs différents, j'ai donc surchargé le constructeur.

Ce qui me donne le droit à l'infobulle visible à la figure suivante lorsque je veux l'instancier.

Une infobulle apparaît lorsque j'instancie la classe Guitare
Une infobulle apparaît lorsque j'instancie la classe Guitare

Deux fonctions avec des arguments de types différents apportent aussi une surcharge :

Sub New(ByVal Notes() As Integer, ByVal NbCordes As Integer)
        MyBase.Notes = Notes
        _NbCordes = NbCordes
    End Sub

    Sub New(ByVal Notes() As Integer, ByVal NbCordes As String)
        MyBase.Notes = Notes
        _NbCordes = NbCordes
    End Sub

Ici le nombre de cordes est une fois un String, une autre fois un Integer, la fonction appelée va dépendre du type passé lors de l'instanciation.

Surcharger la classe mère

Pour surcharger une méthode de la classe mère, la technique est presque la même. Il va juste falloir ajouter le mot-clé Overloads devant la méthode de la classe fille. Ce qui nous donne :

Public MustInherit Class Instrument

    Private _Notes() As Integer

    Public Property Notes As Integer()
        Set(ByVal value() As Integer)
            _Notes = value
        End Set
        Get
            Return _Notes
        End Get
    End Property

    Sub Joue()
        'Ding
    End Sub

End Class

Public Class Guitare
    Inherits Instrument 'Hérite d'Instrument

    Private _NbCordes As Integer

    Sub New(ByVal Notes() As Integer, ByVal NbCordes As Integer)
        MyBase.Notes = Notes
        _NbCordes = NbCordes
    End Sub

    Overloads Sub Joue(ByVal Note As Integer)
        'Ding
    End Sub

End Class

J'ai bien ajouté Overloads devant la méthode Joue de la classe fille, et lors de son appel j'ai le choix entre les deux possibilités : avec ou sans argument.

Dernière chose : on peut « bypasser » une méthode mère. Autrement dit, créer une méthode de la même déclaration dans l'enfant et spécifier que c'est cette dernière qui a la priorité sur l'autre. Cela grâce à Overrides.

Public MustInherit Class Instrument

    Private _Notes() As Integer

    Public Property Notes As Integer()
        Set(ByVal value() As Integer)
            _Notes = value
        End Set
        Get
            Return _Notes
        End Get
    End Property

    Overridable Sub Joue()
        'Ding
    End Sub

End Class

Public Class Guitare
    Inherits Instrument 'Hérite d'Instrument

    Private _NbCordes As Integer

    Sub New(ByVal Notes() As Integer, ByVal NbCordes As Integer)
        MyBase.Notes = Notes
        _NbCordes = NbCordes
    End Sub

    Overrides Sub Joue()
        MyBase.Joue() 'Ding de la mère
        'Ding
    End Sub

End Class

La méthode Joue de la fille prime sur la mère. Le mot-clé Overrides dans la déclaration de la méthode fille est nécessaire, tout comme le mot-clé Overridable dans la déclaration de la méthode mère.

Et j'ai pu utiliser MyBase.Joue() pour que la méthode mère soit quand même appelée.

La surcharge d'opérateurs et les propriétés par défaut

Paramètres dans les propriétés

Avant de comprendre les propriétés par défaut il faut juste que je vous montre comment utiliser un paramètre dans une propriété, ça me semble logique, mais quelques lignes d'éclaircissement ne feront pas de mal. Admettons que je veuille accéder à un certain index dans un tableau à partir d'une propriété, je vais devoir passer un argument à cette dernière :

Module Module1

    Sub Main()
        Dim MaClasse As New Classe
        Console.WriteLine(MaClasse.Variable(0))
        Console.Read()
    End Sub

End Module

Public Class Classe

    Dim _Variable() As String

    Sub New()
        _Variable = {"a", "b", "c", "d"}
    End Sub

    Property Variable(ByVal Index As Integer) As String
        Get
            Return _Variable(Index)
        End Get
        Set(ByVal value As String)
            _Variable(Index) = value
        End Set
    End Property

End Class

Ici (je ne devrais même plus avoir à vous expliquer le code je pense :p ), je demande lors de l'appel de la propriété un paramètre spécifiant l'index, même principe qu'une fonction demandant des arguments : Property Variable(ByVal Index As Integer) As String.

Les propriétés par défaut

Les propriétés par défaut vont vous permettre de vous soustraire à quelques lignes dans votre code source.
Ce concept a pour but d'attribuer à une certaine propriété la particularité d'être « par défaut ».

Lorsque vous voudrez utiliser cette propriété vous n'aurez plus besoin d'écrire MaClasse.Variable(0), mais seulement MaClasse(0).

À utiliser avec précaution si vous ne voulez pas vite être embrouillés. :)

Un simple mot suffit dans le code que je viens de faire, pour la spécifier en défaut :

Module Module1

    Sub Main()
        Dim MaClasse As New Classe
        Console.WriteLine(MaClasse(0))
        Console.Read()
    End Sub

End Module

Public Class Classe

    Dim _Variable() As String

    Sub New()
        _Variable = {"a", "b", "c", "d"}
    End Sub

    Default Property Variable(ByVal Index As Integer) As String
        Get
            Return _Variable(Index)
        End Get
        Set(ByVal value As String)
            _Variable(Index) = value
        End Set
    End Property

End Class

Le mot-clé Default spécifie quelle propriété doit être considérée comme étant celle par défaut.

Surcharge d'opérateurs

Comme son nom l'indique, cette surcharge va être spécifique aux opérateurs +, -, /, *, &, =, <, >, Not, And, et j'en passe…

Vous savez déjà qu'ils n'ont pas la même action en fonction des types que vous utilisez :

  • Entre deux Integer : 10 + 10 = 20 ;

  • Entre deux String : « Sal » + « ut » = « Salut » ;

  • Entre deux Date : CDate("20/10/2010") + CDate("20/10/2010")= 20/10/201020/10/2010.

Bref, rien à voir.

Apprenons à surcharger un opérateur pour notre classe pour que celle-ci réagisse avec ce dernier.

La ligne de déclaration d'une surcharge d'opérateur est un peu plus spécifique :

Shared Operator +(ByVal Valeur1 As Classe, ByVal Valeur2 As Classe) As Classe

Tout d'abord, une surcharge d'opérateur doit être en Shared. Ensuite le mot Operator est suivi de l'opérateur que l'on souhaite surcharger. Ici c'est le « + ». Suivi de deux paramètres (un de chaque côté du « + » :lol: ). Et le type qu'il retourne.

Exemple dans un petit programme :

Module Module1

    Sub Main()

        Dim MaClasseBonjour As New Classe("Bonjour")
        Dim MaClasseSDZ As New Classe(" SDZ")
        Dim MaClasseBonjourSDZ As Classe = MaClasseBonjour + MaClasseSDZ

        Console.WriteLine(MaClasseBonjourSDZ.Variable)
        Console.Read()
    End Sub

End Module

Public Class Classe

    Dim _Variable As String

    Sub New(ByVal Variable As String)
        _Variable = Variable
    End Sub

    Property Variable As String
        Get
            Return _Variable
        End Get
        Set(ByVal value As String)
            _Variable = value
        End Set
    End Property

    Shared Operator +(ByVal Valeur1 As Classe, ByVal Valeur2 As Classe) As Classe
        Return New Classe(Valeur1.Variable + Valeur2.Variable)
    End Operator

End Class

J'ai donc surchargé l'opérateur « + » qui me permet d'additionner les valeurs de l'attribut Variable. Vous pouvez bien évidemment inventer d'autres choses à faire qu'une simple addition.

Les collections

Tout d'abord, et comme d'habitude, qu'est-ce qu'une collection ? À quoi ça va nous servir ?

Eh bien je vais d'abord vous exposer un problème. Vous avez un tableau que vous initialisez à 10 cases. Une case pour un membre par exemple. Si un membre veut être ajouté après la déclaration du tableau, vous allez devoir redéclarer un tableau avec une case de plus (on ne peut normalement pas redimensionner un tableau).

Une collection est sur le même principe qu'un tableau, mais les éléments peuvent être ajoutés ou supprimés à souhait. Pour les Zéros connaissant les listes chaînées, c'est le même concept.

Vous vous souvenez que nous déclarions un tableau en ajoutant accolées au nom de la variable deux parenthèses contenant le nombre d'éléments dans le tableau. Eh bien ici, ce n'est pas plus compliqué, mais ce n'est pas vraiment un tableau que l'on crée, c'est un objet de type collection.

La syntaxe d'instanciation sera donc :

Dim MaListeDeClasses As New List(Of Classe)

Classe est une classe que j'ai créée pour les tests.
Le mot-clé est List(Of TypeSouhaité).

Du même principe qu'un tableau qu'on remplissait à l'instanciation avec = {1, 2, 3}, la liste peut se remplit manuellement ainsi :

Dim MaListeDeClasses As New List(Of Classe) From {New Classe("1"), New Classe("2")}

Avec le mot-clé From.

Cette collection va être vraiment utile, par de simples fonctions on va pouvoir ajouter un élément au bout où à un index spécifié, en retirer un, trouver un élément.

La figure suivante est un schéma d'exemple.

Schéma d'exemple
Schéma d'exemple
  • J'initialise une liste de String. Cette liste va contenir des noms de films. Elle contient au début 4 films.

  • J'utilise la fonction Add sur cette liste, elle a pour effet d'ajouter au bout de la liste « Titanic ».

  • J'utilise la fonction Insert, le premier argument est l'index où ajouter l'objet que l'on passe en second argument. Ici je le place en index 2. Sachant que L'index 0 l'aurait ajouté au début de la liste.

  • Puis j'utilise quelques fonctions que je vais vous détailler :

    • La fonction Contains effectue une recherche dans la liste pour trouver l'élément passé en argument. S'il est présent, elle renvoie True, sinon False.

    • IndexOf se présente de la même manière que Contains. Si elle ne trouve pas l'élément elle renvoie -1, sinon elle retourne l'index de l'élément. La fonction LastIndexOf existe aussi. Si des éléments sont présents en double, IndexOf retourne le premier, LastIndexOf le dernier.

    • Count, quant à elle, renvoie le nombre d'éléments dans la liste. À la même manière que Length sur un tableau. Le dernier index est donc MaListe.Count - 1.

  • Puis j'utilise la fonction Remove pour supprimer l'élément « Titanic ».

  • Et la fonction RemoveAt sert aussi à supprimer un élément, mais cette fois c'est l'index qui est passé en paramètre. J'aurais pu entrer l'index de « Toy Story » en dur (4) ou alors combiner la fonction IndexOf et RemoveAt comme fait ici.

Il existe beaucoup d'autres fonctions possibles sur les collections, je ne peux pas toutes les lister, mais vous allez vite les découvrir grâce au listing qu'effectue Visual Studio lorsque vous écrivez quelque chose.

Regardons un peu côté programmation :

Module Module1

    Sub Main()

        Dim MaListeDeClasses As New List(Of Classe)
        MaListeDeClasses.Add(New Classe("Avatar"))
        MaListeDeClasses.Add(New Classe("Twilight 1"))
        MaListeDeClasses.Insert(0, New Classe("Titanic"))

        For Each MaClasse As Classe In MaListeDeClasses
            Console.WriteLine(MaClasse.Affiche)
        Next
        Console.Read()

    End Sub

End Module

Public Class Classe

    Private _Variable As String

    Sub New(ByVal Variable As String)
        _Variable = Variable
    End Sub

    Function Affiche() As String
        Return _Variable
    End Function

End Class

J'insère des éléments dans ma liste, et grâce à For Each je parcours ces éléments. J'espère que vous allez préférer ça aux tableaux.

Bien évidemment vos listes peuvent être de tous les types, même des objets (comme ici dans l'exemple). Les avantages des listes sont multiples et très modulaires.

Les bibliothèques de classes

Lorsque vous créerez de gros objets, avec des dizaines de fonctions complexes à l'intérieur et qui peuvent être utilisés dans de multiples autres situations, vous voudrez sûrement sauvegarder ces derniers. Vous avez donc deux possibilités. La première étant de simplement copier le fichier .vb contenant la classe et le coller dans votre nouveau projet, la seconde étant de créer une bibliothèque de classes.

La bibliothèque de classes étant un nouveau projet qui aura pour but de créer une DLL, un fichier simple et compilé dans lequel toutes les classes que vous aurez développées seront compilées et facilement réutilisables.

Un hic : vous ne pouvez plus modifier les classes une fois le fichier DLL compilé.

Les créer

Donc pour commencer votre bibliothèque, nouveau projet > Bibliothèque de clases (voir figure suivante).

Créez une bibliothèque de classes
Créez une bibliothèque de classes

Je vais l'appeler « MesClasses ». À l'intérieur je crée une classe :

Public Class MaClasse

        Private _Variable As String

        Sub New(ByVal Variable As String)
            _Variable = Variable
        End Sub

        Function Affiche() As String
            Return _Variable
        End Function

    End Class

End Namespace

Bien sûr si vous avez plusieurs classes à créer, soit vous les insérez dans le même fichier, soit vous créez un fichier par classe.

Une fois votre classe créée et vérifiée, il va falloir générer le projet. Pour ce faire, un clic droit sur le projet dans l'explorateur de solutions et cliquez sur Générer. La DLL est maintenant compilée.

Pour la retrouver, direction VosDocuments\Visual Studio 2010\Projects\MesClasses\MesClasses\bin\DebugMesClasses est le nom de votre projet. Si vous avez modifié la configuration de la génération, il est possible que la DLL se situe dans Release plutôt que dans Debug.

Une fois dans ce répertoire donc, le fichier DLL s'est compilé. Gardez-le bien au chaud, dans un répertoire contenant toutes vos bibliothèques, pourquoi pas.

Image utilisateur

Les réutiliser dans un projet

Pour pouvoir réutiliser nos classes dans un projet, il va falloir effectuer une petite manipulation, ajouter une référence. Nous allons spécifier au projet d'utiliser, en plus du framework qui est pré-incorporé par défaut, notre DLL contenant notre bibliothèque.

Un clic droit sur le projet (où l'on veut utiliser la bibliothèque cette fois), puis Ajouter une référence. Dans l'onglet Parcourir, recherchez votre DLL. Et cliquez sur OK.

Maintenant il va falloir importer le namespace. Vous voyez à la figure suivante que Visual Studio nous aide.

Visual Studio nous aide
Visual Studio nous aide
Imports MesClasses

Et voilà votre bibliothèque est totalement utilisable, comme le montre la figure suivante.

La bibliothèque est totalement utilisable
La bibliothèque est totalement utilisable
  • L'héritage est utile si on souhaite créer plusieurs classes ayant un lien hiérarchique entre elles (véhicule → quatre roues → voiture → décapotable…).

  • La surcharge d'opérateur nous permet de modifier le comportement des opérateurs pour agir avec notre classe. Ainsi Classe1 + Classe2 ne fait pas forcément référence à une addition.

  • Une bibliothèque de classes peut être utile si votre programme est complexe ou si vous voulez diffuser votre structure de classes.

Example of certificate of achievement
Example of certificate of achievement