|
Site |
Cours VB.net |
|
|
|
Composition, groupe d'objets. |
|
|
Est-il possible mettre un objet dans un autre?
On a souvent besoin d'utiliser un ensemble, un groupe d'objets. Comment faire?
Un Objet dans un autre: Composition d'objets:
On parle de contenant-contenu.
On peut créer une Classe qui contient des Objets, une classe qui se compose d'objets.
Exemple classique:
Créons une Classe Point.
Class Point
Private _x As Integer
Private _y As Integer
Public Sub New(ByVal x As
Integer, y As Integer)
_x=x
_y=y
End Sub
...
End Class
On a écrit uniquement le constructeur, il faudrait aussi écrire les property permettant de lire et écrire les coordonnées du point.
Maintenant on a besoin de créer une Classe rectangle qui est définie par 2 points (le coin supérieur gauche et le coin inférieur droit):
Class Rectangle
Private _p1 As Point
Private _p2 As Point
Public Sub New(ByVal x1 As
Integer, ByVal y1 As Integer,ByVal x2 As Integer, ByVal y2 As Integer)
_p1= New Point (x1,y1)
_p2= New Point (x2,y2)
End Sub
...
End Class
Et bien, on utilise la classe Point dans la Classe Rectangle. le constructeur de la classe rectangle instancie 2 points, ce qui appelle le constructeur de la Classe Point.
Groupe d'objets:
Exemple: créons une Classe 'Salarié' avec une Property Nom et un constructeur New nécessitant un nom.
Public Class Salarié
Private _sNom As String
Public Property Nom() As String
Get
Nom = _sNom
End Get
Set
_sNom = Value
End Set
End Property
Public Sub New(ByVal sNom As String)
Nom = sNom
End Sub
End Class
Ensuite pour travailler sur un ensemble de salariés on peut:
A- Utiliser un tableau ou une collection de Salariés (pas bien !!)
B- Créer une Classe contenant des Salariés (good!)
A -Comment utiliser un tableau ou une collection d'objets 'Salarié':
Voyons comment faire avec une approche non objet:
Tableau
Dim LesSalaries(100) As Salarié
Attention, cela crée un tableau de références d'objet, mais pas les objets (Salariées(1) contient Nothing).
Il faut donc créer les objets:
LesSalaries(0) = New Salarié("toto")
LesSalaries(1) = New Salarié("lulu")
LesSalaries(2) = New Salarié("tata")
..
On peut ensuite utiliser LesSalaries(1).Nom pour connaître le nom du salarié d'index 1.
Collection
Dim LesSalaries As New ArrayList 'On crée une collection d'objet ArrayList
Dim s As New Salarié("toto") 'On crée un Salarié
LesSalaries.Add (s) 'On l'ajoute dans l'Arraylist
LesSalariées.Count retourne 1
Pour afficher dans une MsgBox le nom du Salarié d'index 1:
MsgBox(
CType(LesSalaries.Item(0), Salarié).Nom)On remarque que LesSalaries.Item(0) est de type Objet (Les éléments d'un ArrayList sont des objets; Salaries.Item(0).GetType.BaseType.ToString retourne 'Objet') il faut donc caster en 'Salarié' à l'aide de CType:
CType(LesSalaries.Item(0), Salarié) ensuite , on peut utiliser .Nom
En Vb2005 (Framework 2):
On peut utiliser des collections 'génériques'
Dim LesSalaries As New System.Collections.Generic.List(Of Salarié)
On peut ainsi créer une collection fortement typée de 'Salarié'.
Mais utiliser un tableau ou une collection d'objets directement accessibles n'est pas une bonne méthode.
La bonne méthode est de créer une classe qui encapsule la collection (Une Classe qui contient la collection). Voyons donc la suite.
B -Utiliser Une Classe contenant des Salariés:
Voyons comment faire avec une approche objet:
Il faut créer une classe 'LesSalariés' contenant:
-un tableau ou une collection 'Private' complètement encapsulé, donc non accessible à l'extérieur.
-les méthodes 'Public' permettant d'avoir accès au données et de les modifier.
Il y a 4 manières de faire:
1-Créer une Classe contenant une ArrayList
Voyons un exemple utilisant une ArrayList (collection d'objets):
L'arrayList est créée par le constructeur.
Noter l'encapsulation:
une méthode Add permet d'ajouter un 'Salarié' aux 'Salariés' (vu du coté utilisateur).
La méthode Remove permet d'enlever un Salarié.
Dans la classe une méthode Add permet d'ajouter un 'Salarié' à l'ArrayList.
La Property Item permet de retourner un Salarié d'index lIndex.
La Property Count retourne le nombre de Salarié.
Imports System.Collections
Public Class LesSalariésClasse
Private maCol As ArrayList
Public Sub New()
maCol = New ArrayList() 'cela crée une ArrayList
End Sub
Public Function GetEnumerator() As IEnumerator 'permet d'utiliser For Each
GetEnumerator = maCol.GetEnumerator
End Function
Public Function Add(ByVal LeNom As String) As Salarié
Dim UnSalarié As New Salarié(LeNom)
maCol.Add(UnSalarié)
Add = UnSalarié
End Function
Public ReadOnly Property Item(ByVal lIndex As Integer) As Salarié
Get
Item = (CType(maCol.Item(lIndex),Salarié)
End Get
End Property
Public ReadOnly Property Count() As Integer
Get
Count = maCol.Count
End Get
End Property
Public Sub Remove(ByVal Key As String)
maCol.Remove(Key)
End Sub
End Class
Pour utiliser la Classe:
Dim LesSalariés As New LesSalariésClasse() 'création
LesSalariés.Add("Philippe") 'Ajout d'un salarié
LesSalariés.Count retourne 1 'connaître le nombre de salariés
Pour afficher le nom du premier salarié dans une MessageBox:
MsgBox(LesSalariés.Item(0).Nom)
Bien sur on peut utiliser une boucle For Each pour avoir accès à l'ensemble des salariés.
2-Créer une Classe héritant de la Classe ArrayList
On crée une classe héritant de ArrayList, ensuite on va créer une méthode Add pour ajouter un Salarié et une Property permettant de lire le nom du salarié d'index i; comme il existe déjà les membres Add et Index avec la même signature dans la classe parente, il faut remplacer ces membres, on le fait grâce à 'Shadows'.
Dans les nouveaux membres, on appelle les membres de la classe mère (grâce à MyBase)
Imports System.Collections
Public
Class Salariés
Inherits ArrayList
Public
Shadows Sub Add(ByVal S As Salarié)
MyBase.Add(S)
End
Function
Public Shadows ReadOnly Property Index(ByVal i As Integer) As Salarié
Get
Return
Ctype (MyBase.Item(i), Salarié)
End
Get
End
Property
End Class
Là aussi, les éléments d'un ArrayList sont des objets; il faut donc caster en 'Salarié' à l'aide de CType l'Item de l'ArrayList:
Dans l'exemple, on a utilisé une ArrayList, il est possible d'utiliser tout autre type de collections.
3-Créer une Classe héritant de la Classe CollectionBase
CollectionBase est une classe abstraite (ne pouvant pas être utilisée telle quelle), on peut créer une classe qui en hérite.
Cela tombe bien: CollectionBase contient déjà quelques fonctions propres aux collections (Clear et Count), les fonctions qui manquent, qui n'existent pas (Add, Remove, Item) vont être implémentées par vous et à votre manière.
Une propriété Protected appelée List est fournit par CollectionBase et utilisée pour le stockage et l'organisation interne. Quand on crée Add, Remove, Item, on utilise cette propriété List.
Public Class MaCollection
Inherits System.Collections.CollectionBase
Public Sub Add(ByVal a As
Salarié)
' Appelle la méthode
Add de l'objet List pour ajouter un salarié.
List.Add(a)
End Sub
End Class
Remarquons que, bien que l'objet List soit non typé, cette méthode interdit l'ajout de tous les objets n'appartenant pas aux type Salarié. Alors que CollectionBase n'était pas typée, MaCollection est fortement typée car n'acceptant que des 'Salarié'.
On peut aussi ajouter une méthode éliminant un objet de la collection:
Public Sub Remove(ByVal
index as Integer)
' Controle.
If index > Count - 1 Or index < 0 Then
System.Windows.Forms.MessageBox.Show("Index non
valide!")
Else
' Appelle la méthode RemoveAt de l'objet List.
List.RemoveAt(index)
End If
End Sub
On peut enfin ajouter Item:
Public ReadOnly Property Item(ByVal index as Integer) As Salarié
Get
Return CType(List.Item(index), Salarié)
End Get
End Property
Avec le Framework 2, il est possible d'utiliser, au leu de ListArray, une collection générique fortement typée: System.Collections.Generic.List(Of Salarié)
4-Créer une Classe contenant une Classe générique
C'est possible avec le Framework 2
Au lieu de créer une ArrayList dans la Classe, on peut créer une collection générique (
System.Collections.Generic) et lui imposer un type.Ici on va créer une collection de salariés.
Imports System.Collections
Public
Class LesSalariésClasse
Private
maCol As
System.Collections.Generic.List(Of Salarié)
Public
Sub New()
maCol
= New System.Collections.Generic.List(Of
Salarié) 'cela crée une
Collection de salarié
End
Sub
Public
Function Add(ByVal Sal As Salarié)
maCol.Add(Sal)
Add
= Sal
End
Function
Public ReadOnly Property Item(ByVal lIndex As Integer) As Salarié
Get
Item
= maCol.Item(lIndex) 'On a directement un Objet Salarié: pas
besoin de CType
End
Get
End
Property
...
End Class
On peut aussi créer des Stack(Of..) Queue(Of..), Dictionnary(Of..) SortedList(Of..)..
Cette méthode utilisant une collection d'objets complètement encapsulés est une bonne méthode.
Conclusion:
Si une classe doit contenir des objets:
Si vous ne voulez pas que des applications clientes puissent utiliser les objets contenus, définissez ces objets comme Friend ou Private.
|
|
|
|
|