Une notion récurrente de la programmation orientée objet est celle de collection d'objets.
Il s'agit, dans les grandes lignes, de gérer un ensemble d'objets de même type (ou type dérivé, polymorphisme oblige !) dans un objet de niveau supérieur.
Avec une classe pouvant contenir des objets dont le type de base est connu, on pourra y définir des méthodes de classement, de tri, et autres traitements ensemblistes.
WinDev propose les tableaux comme conteneurs d’éléments multiples, y compris les objets. Nous partirons sur cette base car :
Ce tableau, combiné à un pointeur entier sur l'élément courant du tableau, nous donne une collection basique et parcourable :
mtab_Obj est un tableau de MaClasse // conteneur des éléments de la collection
mn_Curseur est un entier // élément courant durant les parcours
Toutefois, ce typage "ultra-fort", fait qu'il n'est pas possible de créer une collection générique acceptant n'importe quel type d'objet : un tableau d'objets ne peut être déclaré qu'avec un type d'objet bien précis. Bien que cela puisse gérer un type de base et tous ses dérivés, on doit donc créer une collection par type d'objet de base pour lesquels on souhaite bénéficier de ce patron.
Oui, sauf si... le tableau est déclaré comme suit :
mtab_Obj est un tableau d'objets dynamiques
Il est possible de stocker tout et n'importe quoi dans cette collection. Mais alors on perd les avantages du typage fort qui permet de contrôler qu'on ne mélange pas les choux et les carottes... puisque le tableau accepte n'importe quel type d'objet.
On aimerait bien bénéficier du contrôle de type tout en n'écrivant qu'un seul patron de collection. C’est assez frustrant car en C++ par exemple (et grâce à la Standard Template Library) cette collection peut se déclarer sous forme de liste simple :
Std::list<MaClasse> MaCollectionTypee;
Cette liste peut contenir des instances de MaClasse ou bien héritant de MaClasse. Comment éviter de créer une collection pour chaque type d’objet tout en conservant un contrôle de typage en WLangage ? Grâce à la compilation dynamique !
Puisqu'il n'est pas possible de déclarer à la volée un tableau avec un type non défini, procédons comme suit :
CL_TypableElementsCollection est une Classe
PRIVÉ
mptab_Obj est un tableau dynamique // Pointeur sur un tableau conteneur
mn_Curseur est un entier // élément courant durant les parcours
FIN
Le tableau de la collection est déclaré comme dynamique, rien n'est fixé. Puis il faut l’allouer au constructeur de la manière suivante :
PROCEDURE Constructeur(lpo_ObjetType est un objet dynamique)
ls_CodeInit est une chaîne =""":mptab_Obj"" = allouer un tableau de 0 "+lpo_ObjetType..Classe+" dynamique"
ExécuteCode(ls_CodeInit)
Et c'est là toute l'astuce :
- récupérer le type de l'objet fourni au constructeur grâce à RécupèreDéfinition() ou la propriété ..Classe de l'objet
- construction de la chaine """:montableau"" = allouer un tableau de 0 "+poObjetType..Classe (les doubles guillemets sont indispensables, sans quoi ExecuteCode() qui va suivre ne verra pas les membres de la classe)
- ExecuteCode() de cette chaine, ce qui nous alloue le tableau avec le bon type.
On a bien utilisé ExecuteCode() et non pas Compile(), car cette dernière crée une procédure globale au projet (la portée n’est donc pas adaptée puisqu'on est au constructeur de la collection, Compile() ne peut pas accéder aux membres de la classe).
ExecuteCode() effectue une compilation à la volée, unique (pas de procédure générée pour toute l'exécution) , et pouvant exploiter les variables du traitement en cours.
L'allocation typée et paramétrable est faite ! Très bien, mais lors de l'ajout d'un élément d’un type incompatible à la collection, le contrôle du type natif fait que l'on obtient un null dans le tableau, car le type ne convient pas (aucune erreur n'est générée).
Ça tombe bien, un mécanisme de contrôle de type supportant le polymorphisme (réalisé ici est intégrable à la collection et utilisé lors de l’ajout d’éléments à la collection.
Le projet Collection fournit une implémentation complète de cette collection, avec des exemples de manipulations et de traitements ensemblistes.
#896266D
Atelier de Génie Logiciel