Les modules de classe sont une extension extrêmement puissante des simples modules. En effet, nous approchons ainsi quelque peu de la POO (Programmation orientée Objet), telle que celle pratiquée avec C++, C#, Java, et autre Eiffel. Visual Basic est la la fois plus simple et moins puissant que ces langages, mais attention : En effet, même si vous avez déjà quelque peu bidouillé avec VBA, la création, l'utilisation et la rationnalisation des modules de classe demande bien plus de pratique, et si vous n'êtes pas un programmeur véritablement aguerri, et en tout cas avec une excellente connaissance des concepts tels que Procédures paramétrées, variables typées, variables globales, visibilités des fonctions et des procédures, il y a bien des chances pour que vous considériez cet article comme du chinois, ou tout du moins ne compreniez pas vraiment l'utilité de ce concept de classe. Accrochez-vous : C'est parti !
Avant de commencer l'étude des classes à proprement parler, nous allons d'abord créer une variable d'un type particulier, qui contient des sous-variables.
Allez dans un module normal (pas un module de classe), et écrivez directement :
Type Coordonnee
Nom As String
Prenom As String
Age As Integer
End Type
On ne peut pas mettre ce code dans une procédure. Il faut que ce soit en en-tête de Module. Il s'agit d'une variable Coordonnee compoosée de 3 sous variables.
Créez maintenant juste plus bas un module, comme ceci :
Sub Remplissage()
Dim MonCopain As Coordonnee
MonCopain.Nom = "Dupont"
MonCopain.Prenom = "Jean"
MonCopain.Age = 40
MsgBox MonCopain.Prenom
End Sub
Voilà comment on peut ainsi créer des variables composées
: C'est déjà une sorte d'objet. Passons maintenant aux choses
sérieuses !
Nous allons d'abord créer une Classe, grace à l'insertion d'un nouveau module de classe :
Imaginons le concept d'un simple bistrotInsertion/Module de classe (et pas nouveau module, sinon, ce n'est pas un module de classe)
Le sauvegarder sous Bistrot
Dans ce module, installer le code (Minable, j'en conviens) suivant :
Public NombreClient
Sauvegardez.
Voici notre première classe réduite à sa plus simple expression : En effet : Elle ne comporte ni procédure ni fonction, ni rien d'autre qu'une simple variable : NombreLitre
Nous allons la tester. La manière la plus simple consiste à créer un module (normal cette fois), et à y insérer le code suivant : Il s'agit de créer une variable de type Bistrot (As New Bistrot). C'est comme une variable normale, mais c'est cette fois une variable dite OBJET, c'est à dire qu'elle sera d'une structure beaucoup plus complexe qu'un type de données String, ou Single qui sont considérées comme des variables de type SCALAIRES (Simples)
Sub TesterLaClasse()
Dim CafeDeLaGare As New Bistrot
End Sub
Exécutez cette procédure TesterLaClasse : Il ne se passe rien, mais il n'y a pas d'erreur.
Nous allons maintenant placer la valeur 5 dans cette variable NombreLitre, et l'afficher à l'aide d'un MsgBox. Nous pouvons nous permettre cela uniquement grâce au fait d'avoir déclaré NombreLitre en Public, sinon, une erreur de compilation aurait eu lieu :
Sub TesterLaClasse()
Dim CafeDeLaGare As New Bistrot
CafeDeLaGare.NombreClient = 5
MsgBox CafeDeLaGare.NombreClient
End Sub
De cette même façon, il est donc possible de déclarer 2 INSTANCES de Bistrot, chacune étant indépendante de l'autre, comme ceci :
Sub TesterLaClasse()
Dim CafeDeLaGare As New Bistrot
Dim ChezGaston As New Bistrot
CafeDeLaGare.NombreClient = 5
ChezGaston.NombreClient = 10
MsgBox CafeDeLaGare.NombreClient' 5
MsgBox ChezGaston.NombreClient' 10
End Sub
Maintenant, il est possible de créer des Subs directement dans la Classe. Modifiez votre module de classe Bistrot comme ceci :
Public Sub Cuisiner()
MsgBox "Je cuisine"
End Sub
Et dans votre autre module de test TesterLaClasse, faites un appel :
Sub TesterLaClasse()
Dim CafeDeLaGare As New Bistrot
CafeDeLaGare.Cuisiner ' Affichera "Je cuisine"
End Sub
Nous avons pu appeler ce sub grâce au fait qu'il est déclaré comme Public, sinon, une erreur de compilation serait survenue. Un Sub dans un module de classe est appelé alors une METHODE.
Il est possible de paramétrer la méthode comme ceci :
Modifications à faire dans le module de classe Bistrot (Appelons désormais ce module de classe simplement "La classe bistrot") :
Public Sub Cuisiner(QuelRepas)
MsgBox "Je cuisine " & QuelRepas
End Sub
Modifications à faire dans TesterLaClasse :
Sub TesterLaClasse()
Dim CafeDeLaGare As New Bistrot
CafeDeLaGare.Cuisiner "Un steack"
CafeDeLaGare.Cuisiner "Une omelette"
End Sub
Constatez l'absence de parenthèses. Vous allez donc maintenant pouvoir appeler la méthode Cuisiner de la classe Bistrot avec un paramètre.
On peut également placer des fonctions dans les classes. Ajoutez la fonction PreparerLesTables() dans la classe Bistrot :
Public Function PreparerLesTables()
PreparerLesTables = "Les tables sont préparées"
End Function
Cette fonction s'appelle comme une fonction normale. A nouveau, pour qu'elle puisse s'appeler depuis ailleurs que dans un MEMBRE de la classe elle-même, il est nécessaire de la précéder de Public. Un membre est une fonction, une procédure, une variable ou une propriété de la classe (Nous n'avons pas encore abordé les propriétés)
Modifiez TesterLaClasse pour appeler cette nouvelle fonction :
Sub TesterLaClasse()
Dim CafeDeLaGare As New Bistrot
MsgBox CafeDeLaGare.PreparerLesTables()
End Sub
Constatez l'apparition des parrenthèses vides indispensables en cas d'appel à une fonction, par opposition aux procédures Sub. Constatez également l'obligation du MsgBox. En effet, on DOIT récupérer la valeur "Les tables sont préparées" :
CafeDeLaGare.PreparerLesTables()
donnerait une erreur. On aurait pu également stocker cette valeur "Les tables sont préparées" dans une variable, comme ceci :
Dim EtatDesTables
EtatDesTables = CafeDeLaGare.PreparerLesTables()
Imaginons la même fonction mais avec 3 paramètres : Le genre de la nappe, sa couleur, et s'il faut mettre des bougies. Modifiez Bistrot.PreparerLesTables comme suit :
Public Function PreparerLesTables(GenreDeNappe, CouleurNappe, MettreBougie)
Dim JePrepare
JePrepare = "Je met des nappes en " & GenreDeNappe
JePrepare = JePrepare & " " & CouleurNappe & "s "
If MettreBougie = True Then
JePrepare = JePrepare & "avec une bougie"
End If
PreparerLesTables = JePrepare
End Function
Et appelez maintenant cette nouvelle fonction comme ceci :
Sub TesterLaClasse()
Dim CafeDeLaGare As New Bistrot
MsgBox CafeDeLaGare.PreparerLesTables("papier", "rouge", True)
End Sub
Il va afficher :
Je met des nappes en papier rouges avec une bougie
Les propriétés permettent une certaine syntaxe d'appel aux membres de Bistrot.
Corrigez la classe Bistrot comme suit :
Property Let Musique(QuelGenre)
End Property
Les Property sont par défaut Publiques : On pourra donc les appeler sans problème depuis l'extérieur. QuelGenre est un paramètre OBLIGATOIRE. On ne peut PAS créer une property sans paramètre. Nous verrons plus tard comment mettre plusieurs paramètres tels que Property Let Musique(QuelGenre, QuelVolume) par exemple.
Le Let veut dire qu'il s'agit d'une propriété qui va ACCUEILLIR un paramètre lors de l'appel. Ce qui veut dire que cette propriété sera dite EN ECRITURE, puisqu'on va pouvoir ECRIRE dedans, comme ceci :
Sub TesterLaClasse()
Dim CafeDeLaGare As New Bistrot
CafeDeLaGare.Musique = "Jazz"
End Sub
Voilà. En exécutant ce code, il ne va pas se passer grand chose, c'est le moins qu'on puisse dire : En effet, Il se contente d'envoyer "Jazz" dans le paramètre QuelGenre.
Le but étant bien évidemment de traiter ce paramètre, en le gardant en mémoire, par exemple en mémorisant le résultat dans une variable locale comme ceci :
Dim GenreMusique
Property Let Musique(QuelGenre)
GenreMusique = QuelGenre
End Property
On peut effectivement se poser la question puisque l'appel à une Property Let à comme forme NomDeLaClasse.NomDeLaPropertyLet = QuelqueChose
Et bien oui, on peut, et l'appel se fera alors comme ceci :
Prenons l'exemple d'une Property Let qui allume le bistrot (Un certain nombre de lustres, de chandelles, le tout à une certaine puissance) :
Property Let Allumer(Lustre, chandelle, Puissance)
MsgBox "Lustre : " & Lustre
MsgBox "Chandelle : " & chandelle
MsgBox "Puissance : " & Puissance
End Property
Qui s'appelle de la manière suivante :
Sub MettreLaLumiere()
Dim CafeDesAmis As New Bistrot
CafeDesAmis.Allumer(2, 10) = "60 Watts"
End Sub
Mais alors, on est en droit de se demander pourquoi créer une propriété, et pas simplement déclarer GenreMusique comme étant une variable Public, et directement injecter le genre de musique dedans, comme ceci :
CafeDeLaGare.GenreMusique = "Jazz"
Ce qui reviendrait effectivement au même. Mais en fait, la propriété étant carrément tout un bout de code visual Basic, on peut se permettre de faire beaucoup plus que d'attribuer une simple valeur à une variable, comme par exemple, définir automatiquement le volume sonore suivant le genre de musique choisie, ou simplement s'il y a de la musique. Changez la classe Bistrot comme ceci :
Dim AvecMusique
Dim GenreMusical
Dim VolumeMusical
Property Let Musique(QuelGenre)
AvecMusique = True
Select Case QuelGenre
Case "Jazz":
GenreMusical = "Détendu"
VolumeMusical = 4
Case "Hard-Rock":
GenreMusical = "Violent"
VolumeMusical = 10
Case "Classique"
GenreMusical = "Calme"
VolumeMusical = 1
Case "Silence"
GenreMusique = ""
AvecMusique = False
VolumeMusical = 0
End Property
Voyez comme le simple envoi d'une valeur à une propriété peut engendrer des grands changements.
Si vous réfléchissez un peu, vous constaterez qu'on aurait pu faire la même chose avec une procédure Musique (Sub), comme ceci :
Dim AvecMusique
Dim GenreMusique
Dim VolumeMusical
Public Sub Musique(QuelGenre)
AvecMusique = True
Select Case QuelGenre
Case "Jazz":
GenreMusical = "Détendu"
VolumeMusical = 4
' Etc, la même chose qu'avec le property
End Sub
L'appel à cette procédure depuis TesterLaClasse aurait alors été :
CafeDeLaGare.Musique "Jazz"
Au lieu de
CafeDeLaGare.GenreMusique = "Jazz"
On aurait pu même le transformer en Function, mais dans ce cas, il aurait fallu renvoyer le résultat dans une variable du style :
Resultat = CafeDeLaGare.Musique ("Jazz")
Enfin bref, voyez comme les Property, Sub et Function peuvent s'interchanger. Donc, finalement, pourquoi utiliser les Property ?
Simplement parce qu'elles permettent de LIRE et d'ECRIRE avec le même nom ! Je m'explique : Dans la Classe bistrot, créez une Property Let toute simple :
Dim GenreMusique
Property Let Musique(QuelGenre)
GenreMusique = QuelGenre
End Property
C'est la possibilité pour un appel externe d'IMPOSER le style musical :
Dim GenreMusique
Sub TesterLaClasse()
Dim CafeDeLaGare As New Bistrot
CafeDeLaGare.Musique = "Jazz"
End Sub
Maintenant, dans la classe Bistrot, ajoutez la MEME propriété Musique, mais avec GET, pour que finalement votre Classe ressemble à ceci :
Dim GenreMusique
Property Let Musique(QuelGenre)
GenreMusique = QuelGenre
End Property
Property Get Musique()
Musique = GenreMusique
End Property
A nouveau, on pourrait se demander pourquoi créer une Property Let et Get, puisqu'à priori, il suffit de lire ou d'écrire dans la variable GenreMusique qui serait simplement déclarée Public pour que tout le monde puisse y accéder sans restriction, comme ceci :
Contenu de la classe Bistrot :
Public GenreMusique
Appel depuis l'extérieur :
Sub TesterLaClasse()
Dim CafeDeLaGare As New Bistrot
CafeDeLaGare.GenreMusique = "Jazz"
MsgBox CafeDeLaGare.GenreMusique
End Sub
C'est effectivement strictement la même chose. Mais je fais la même remarque qu'avant : En effet, lorsqu'on met de la musique, on voudrait définir :
Et lorsqu'on lit la musique, on ne voudrait par exemple pas seulement le style de la musique, mais un message personnalsié, comme par exemple :
"Jazz à volume moyen"
"Hard-Rock Plein Pot"
"Musique classique douce"
Maintenant, la simple utilisation d'une variable ne suffit plus.
Voici le code complet de la classe Bistrot, avec les 2 Property Musique :
Dim AvecMusique
Dim GenreMusical
Dim VolumeMusicalProperty Let Musique(QuelGenre)
AvecMusique = True
Select Case QuelGenre
Case "Jazz":
GenreMusical = "Jazzy"
VolumeMusical = 4
Case "Hard-Rock":
GenreMusical = "Hardeux"
VolumeMusical = 10
Case "Classique":
GenreMusical = "Bien habillé"
VolumeMusical = 1
Case "Silence":
GenreMusique = ""
AvecMusique = False
VolumeMusical = 0
End Select
End Property
Property Get Musique()
If AvecMusique = False Then
Musique = "Pas de musique"
Exit Property
End If
Musique = GenreMusical & ", "
Select Case VolumeMusical
Case 1 To 3: Musique = Musique & "Calme"
Case 3 To 5: Musique = Musique & "Détendu"
Case 6 To 8: Musique = Musique & "Dynamique"
Case Is > 8: Musique = Musique & "Très forte"
End Select
End Property
Et le code de l'appel à la classe :
Sub TesterLaClasse()
Dim CafeDeLaGare As New Bistrot
CafeDeLaGare.Musique = "Jazz"
MsgBox CafeDeLaGare.Musique
End Sub
Property Let Machin(Truc)
MsgBox "Je suis dans Let" ' (Truc
vaut 1)
End Property
Property Get Machin()
MsgBox "Je suis dans Get"
End Property
Dim Troulala As New
ClasseDebile
Sub TestBidon()
Troulala.Machin = "N'importe
quoi" ' Appelle Let Machin(Parametre)
VariableQuelconque = Troulala.Machin
' Appelle Get Machin()
End Sub
Un exemple parlant va être plus compréhensible qu'un long disours :
Ce que l'on appelle le constructeur en POO (Programmation Orientée Objet) désigne simplement une procédure exécutée automatiquement immédiatement lors du premier appel à quoi que ce soit dans la classe en question en utilisant le nom de procédure-clé Class_initialize. Exemple :
Même commentaire avec le destructeur qui s'exécutera à la fin du code VBA
Private Sub Class_Terminate()
MsgBox "Fin"
End Sub
Tutoriel très instructif ici : http://cafeine.developpez.com/access/tutoriel/classe/
Plus d'infos (en anglais) sur cette page de Microsoft :
http://www.microsoft.com/AccessDev/Articles/GetzCh3.HTM
---