Site:  Cours VB.net  
5.2 Création de Classe.

On a vu qu'il existait des classes prédéfinies (celle du Framework par exemple) mais on peut soi même

CREER SES PROPRES CLASSES:

 

Maintenant on est DANS la boite.

 

Revenons une nouvelle fois sur la notion de Classe et d'Objet.

On va créer une classe 'Médicament'( c'est l'objet de ce chapitre).

Un 'Médicament' possède les variables:

Nom

Laboratoire

Nombre de médicament.

..

Il faut donc pouvoir 'regrouper' ces variables pour un médicament précis. Pour regrouper ces variables, on utilise une structure particulière: la Classe.

Une Classe 'Medicament' aura:

Medicament.Nom

Medicament.Laboratoire

Medicament.NbdeMedicament

 

Avec cette Classe (la structure, le moule), on peut créer (instancier) un Objet MonMedicament.

Dim MonMedicament As New Medicament

Il comporte les variables (données):

MonMedicament.Nom

MonMedicament.Laboratoire

MonMedicament.NbdeMedicament

Il comporte des méthodes (comportement):

MonMedicament.GetNom  est une méthode

L'utilisateur de l'objet ne voit que le nom de la méthode (l'interface), il ne voit pas le code de la procédure (l'implémentation). Il y a bien encapsulation.

Une fois cette classe créée, du coté utilisateur, comment l'utiliser?

Pour instancier un objet Medicament: Dim MonMedicament As New Medicament()

Donner une valeur à une propriété: MonMedicament.Nom= "Aspirine": MonMedicament.Laboratoire="RP"

Récupérer la valeur d'une propriété: LeNom=MonMedicament.Nom  : Nb= MonMedicament.NombreMedicament

Pour la suite de ce chapitre, nous sommes DANS la Classe de l'objet ( et non dans l'application utilisatrice).

 

Créer une Classe

Menu Projet puis Ajouter une Classe.

Entrée 'Medicament' dans la zone nom puis OK

Une nouvelle fenêtre de module est ajoutée à notre projet, contenant le code suivant:

Public Class Medicament

End Class

Le mot avant Class indique la portée de la classe:

Public (Classe instanciable dans et hors du projet, utilisable par un autre programme)

Private (Classe instanciable que dans elle même!!)

Friend (Classe instanciable dans le projet )

Protected (Classe instanciable uniquement dans les classes dérivées)

On peut ajouter:

MustInherit: Cela donne une classe non instanciable, on ne peut pas créer d'objet avec!! Alors à quoi cela sert!! A fournir une base pour des classes qui en hériteront. on appelle ces classes des classes abstraites.

NotInheritable: Cette classe ne peut-être héritée.

 

Ajouter des variables dans une classe:

On parle de variable ou 'Attribut' permettant d'associer des données à une Classe.

La variable peut être 'Privée' et non visible à l'extérieur:

Private _mNom As String

Il est conseillé de mettre un '_' au début du nom d'une variable privée puis une majuscule au début de chaque mot sauf le premier.

Elle peut être 'Public' , visible à l'extérieur et donc non encapsulée.

Public Laboratoire As String

Il est conseillé de mettre une majuscule au début de chaque mot formant le nom de la variable public.

A l'extérieur , si on instance M comme un médicament (Dim M As New Médicament) , M.Laboratoire est valide.

On peut définir un champ 'Public' en lecture seule qui a une valeur constante:

Public ReadOnly NombreMedicament=2000

 

Vous pouvez ajouter à votre variable : Shared. Cela signifie que la variable déclarée comme Shared est partagée par toutes les instances de la classe : C'est une variable de classe et non une variable d'instance.

Une variable Shared est même utilisable sur le nom de la classe , sans instancier.

 

Exemple:

Public Class Medicament

    Public Laboratoire As String    'variable d'instance

    Public Shared Societe as String 'variable de classe Shared

End Class

 

Dim M1 As New Medicament

Dim M2 As New Medicament

 

M1.Laboratoire= "MVV"

M2.Laboratoire= "VVT"

Chaque instance à sa propre variable  Laboratoire (Non Shared)

 

M1.Societe="ooo" entraîne que M2.societe est aussi égal à "ooo"

La propriété Societe de toutes les instances de Medicament a la même valeur

 

Medicament.Societe est aussi égal à "ooo"

Ici on a directement utilisé le nom de la classe.

 

(Ne pas confondre avec une variable Static qui est une variable qui conserve sa valeur, mais qui a une valeur pour chaque instance).

 

Une variable, comme tous les membres d'une classe peut être, Private, Public, mais aussi Protected (accessible par les seules méthodes de la classe ou des objets dérivés)

Il faut en général déclarer les variables interne en 'Private': elles sont internes et non accessible à l'extérieur de la Classe.

 

 

Ajouter des propriétés grâce à 'Property'

Les propriétés permettent d'associer des données à une Classe.

On rappelle qu'une Property peut être utilisée comme cela:

Dim MonMedicament As New Medicament()

MonMedicament.Nom= "Amoxicilline" : Nom est une Property.

Vu de l'extérieur cela pourrait ressembler à une variable, en fait dans l'implémentation c'est complètement différent. Il y a du code permettant d'écrire ou de lire la property.

Pour créer une Property:

Tapez 'Property Nom' puis validez, la définition de la propriété est générée en faisant apparaître

Property Nom()
Get 
End Get

Set (By Val Value)
End Set
End Property

J'ajoute Public pour que cette propriété soit accessible hors de la classe, j'indique que c'est une String. Lors de la lecture de la propriété (par l'utilisateur de l'instance) Get retourne (grâce à Return) la valeur _mNom qui est une variable privée de la classe et qui sert à stocker la valeur de la propriété. Lors de l'écriture de la variable, Set récupère la valeur dans Value et la met dans _mNom:

Public Class Medicament

 

'Variable privée (Attribut) servant à stocké en interne le nom.

Private _mNom As String

 

'Propriété Nom

Public Property Nom() as String
Get 
    Return _mNom
End Get
Set(By Val Value)
    _mNom=value
End Set

End Property

 

End Class

 

Encapsulation:

La variable '-mNom' est encapsulée: l'utilisateur qui utilise une instance de la classe, ne voit pas ce qui se passe (ici c'est très simple) quand il utilise le nom, il ne voit pas l'implémentation (l'implémentation c'est Get...Set...), il ne voit que l'interface c'est à dire .Nom ; Il n'a pas accès à _mNom.

 

Si l'utilisateur tape: MonMedicament.Nom=" Aspirine" , c'est le code Set..EndSet qui est exécuté.

Si l'utilisateur tape: DIm s As String= MonMedicament.Nom , c'est le code Get..EndGet qui est exécuté.

 

 

 

 

Une propriété peut être en lecture seule:

Public ReadOnly Property InitialeNom() As String
Get
 Return Left(_mNom,1)
End Get
End Property

 

Mais aussi en écriture seule grâce à WriteOnly.

 

Les propriétés comme les méthodes peuvent être Public, Private, Protected, Friend, ProtectedFrient:

 

 

 

Méthode:

Une Classe peut contenir un comportement sous forme de procédures et fonctions contenant du code.

On peut ajouter une méthode à une Classe:

Les méthodes d'une classe sont les procédures Sub ou Function déclarées dans la classe.

Elles sont habituellement 'Public'.

 

Une méthode peut contenir du code effectuant un traitement:

Public Sub Dessine() As Double
' Code
End Sub

 

Une méthode peut aussi être utilisée pour lire ou écrire des variables privées, on parle dans ce cas d'accesseurs:

 

Public Class Medicament

'Variables ou Attributs

Private _nom As String

 

'Accesseurs

Public Function GetNom() As String

    Return _nom

End Sub

 

'modificateurs

Public Sub SetNom (ByVal N As String)

    Me._nom= N

EndSub

End Class

 

SetNom est une mutateur.

 

 

Récapitulatif  Property, méthodes.

A- Un objet peut être vu comme un regroupement de données (variables et propriétés).

La différence entre une variable et une Propriété (Property) est qu'alors que la variable est une simple variable , la Property est contrôlée par du code interne qui peut modifier le comportement de la lecture ou de l'écriture de la Property.

B- Mais un objet va plus loin: il peut contenir un comportement sous forme de procédures et fonctions contenant du code. (Ce sont les méthodes de l'objet). Elles représentent le comportement commun de tous les objets appartenant à la classe.
 

 Tous les éléments de la Classe peuvent être Public (visibles par l'utilisateur de la classe) ou Private (non accessibles à l'utilisateur de la classe et utilisés en interne dans la classe)

  On voit aussi qu'il faut que les variables soient 'Private' et les méthodes et Property  'Public'.

 

 

 

Constructeur:

Un constructeur est une procédure  exécutée lors de l'instanciation.

Dans le module de classe, elle est définie par:

Sub New()

End sub

On peut ajouter des paramètres qui serviront à instancier.

Par exemple pour instancier et donner le nom en même temps:

Sub New(ByVal LeNom As String)

    _mNom=LeNom

End sub

Cela permet  Dim M As New Medicament("Aspirine")

On peut définir plusieurs constructeurs avec un nombre de paramètres différents (plusieurs signatures), dans ce cas il y a surcharge, le constructeur  par défaut étant celui sans paramètres.

 

Une autre manière de faire est d'utiliser une méthode Initialise:

Créons une classe avec une méthode Initialise.

Classe Homme

Private _Nom As String

Private _Prenom As String

Public Sub initialise(ByVal N As String, ByVal P As String)

    Me._nom = N

    Me._prenom = P

End Sub

End Class

_nom, _prenom  étant des données privées de la classe Homme, les instructions :

dim p as New Homme()

p._prenom="Philippe" est refusée

On écrira donc :

dim p as New Homme

p.initialise("Monnom", "Philippe")

 

 

Destructeur:

 

Un objet est détruit:

 

- en lui affectant la valeur Nothing.

 

- si on sort de sa portée.

 

Une procédure Finalize  (appartenant à la Classe Objet) est automatiquement appelée quand l'objet est détruit.

 

On peut ajouter une procédure Finalize à notre classe, qui redéfini la procédure Finalise de la Classe 'Objet'.

 

Protected Overrides Sub Finalize ()

End Sub

 

On peut y mettre le code  libérant les ressources ou d'autres choses.

 

Noter que la procédure Finalize est ici la redéfinition (d'ou 'Overrides') de la procédure Finalize (qui est Overridable) de la Classe Objet.

 

Attention la méthode Finalize est exécutée quand l'objet est réellement détruit (Objet=Nothing le rend inutilisable mais il est toujours présent en mémoire). C'est parfois très tardivement que l'objet est détruit: quand il y a besoin de mémoire (c'est le Garbage Collector qui entre en action) ou à la sortie du programme.

 

 

Pour forcer la destruction on peut utiliser l'interface IDisposable:

Il faut mettre dans l'entête de la classe

Implements IDisposable

 

et mettre dans le code de la classe

 

Public Sub Dispose() Implements System.IDisposable.Dispose

' Code libérant les ressources (Base de données, connexion, Objets systèmes..)...

End sub

 

C'est une méthode Public, on peut l'appeler de l'application cliente:

M.Dispose()

M=Nothing

 

Là aussi attention, Dispose doit être appelé de manière explicite (il faut le faire, ce n'est pas automatique); quand on fait M.dispose, la procédure Dispose et le code qu'il contient sont exécutés immédiatement, par contre c'est toujours le Garbage Collector qui décide quand Finalise sera exécuté.

 

 

 

 

Dans la pratique quelle est d'utilité de gérer la destruction autrement que par Objet=Nothing si le Garbage Collector nettoie la mémoire? C'est une question.

 

Réponse donnée par Microsoft:

Votre composant a besoin d'une méthode Dispose s'il alloue des objets système, des connexions à la base de données et d'autres ressources rares qui doivent être libérées dès qu'un utilisateur a fini de se servir d'un composant.

Vous devez également implémenter une méthode Dispose si votre composant contient des références à d'autres objets possédant des méthodes Dispose.

 

 

 

Surcharge

 

On peut surcharger un constructeur.

Pour  cela il suffit de rajouter autant de procédure New que l'on veut avec pour chacune un nombre de paramètre différent (signatures différentes).

 

Exemple: On peut surcharger un constructeur:

 

Class Figure

Sub New()

    Bla Bla

End Sub

 

Sub New( ByVal X As Integer, ByVal Y As Integer)

     Blabla

End Sub.

End Class

 On peut donc instancier la classe correspondante de 2 manières:

Dim A As New Figure    'Constructeur par défaut

ou

Dim A As New Figure(100,150)

 

On peut surcharger une property.

Pour  cela il suffit de rajouter des procédure Property ayant le même nom de méthode avec pour chacune un nombre de paramètre différent (signature différente)

On peut ajouter Overloads mais c'est facultatif.

Exemple surchargeons un membre:

Class Figure

Public Overloads Property Calcul()

    Bla Bla

End Sub

 

Public Overloads Property Calcul( ByVal X As Integer, ByVal Y As Integer)

     Blabla

End Sub.

End Class

 

Evènement:

On peut définir un évènement pour la classe.

Dans la classe:

Exemple:

je crée une classe nommé 'Class1' qui contient un membre 'Texte'( Property Texte), si 'Texte' change, alors on déclenche l'évènement TextChange:


 

Public Class Class1

Private _mTexte As String

 

' Déclare un évènement

Public Event TextChange(ByVal UserName As String)

 

Public Property Texte()

Get

    Return _mTexte

End Get

Set(ByVal Value)

If Value <> _mTexte Then

  RaiseEvent TextChange("hello")'<= déclenchement de l'évènement par RaiseEvent

End If

_mTexte = Value

End Set

End Property

 

End Class


 

Si l'application cliente modifie la propriété .Texte d'un objet Class1  alors on compare l'ancien et le nouveau texte, s'il est différent on déclenche un évènement TextChange.

 

Dans l'application cliente:

Private WithEvents  M As Class1

 

M= New Class1()

 

Private Sub M_TexteChange(ByVal v As String) Handles M.TextChange

    MsgBox("le texte a changé")

End Sub

Ici on demande simplement quand le texte change, d'ouvrir une MessageBox.

 

Lors de l'utilisation:

M.Text="Nouveau text" 'déclenche  la Sub M.TextChange qui dans notre exemple simple ouvre une MessageBox indiquant que le texte à changer.

 

On remarque que la Classe définit l'évènement, la procédure correspondant à l'évènement est dans l'application cliente.(De la même manière que quand on clique sur un objet bouton cela déclenche la procédure Bouton-Click.)
 

Exception:

Il est parfois utile de déclencher une exception: si l'utilisateur de la classe donne par exemple une valeur invalide à une property, une exception se déclenche indiquant que la donnée est invalide.

Dans l'exemple suivant si l'utilisateur affecte à la propriété Mavaleur une valeur négative, une exception est déclenché (Maclasse.Mavaleur=-2)

Public Property MaValeur() As Integer

    Get

    ..

    End Get

    Set (ByVal Value As Integer)

        If Value>=0 Then

            _mValeur= Value

        Else

            Throw New Exception ("La valeur " & Value.ToString & " est invalide")

        End If

    End Set

End Property

 

Les Classes partielles:

Les classes 'Partielles' sont possible en VB2005 (Framework 2).

Les types partiels permettent la définition d'une classe unique dans plusieurs fichiers source. La définition a une déclaration normale dans un fichier :

Public Class MaClasse
    'implementation...
End Class

Dans d'autres fichiers source, utilisez le mot-clé Partial pour indiquer au compilateur que ce code est la suite de la définition de classe d'origine :

Partial Public Class MaClasse
    'implementation...
End Class