DOCUMENTATION EN LIGNE
DE WINDEVWEBDEV ET WINDEV MOBILE

Aide / WLangage / POO (Programmation Orientée Objet)
  • Présentation d'une classe
  • Exemple de classe
  • Création et déclaration d'une classe
  • Création d'une classe
  • Syntaxe de déclaration de la classe et de ses éléments
  • Déclaration d'une classe
  • Syntaxe
  • Exemple
  • Déclaration des membres d'une classe
  • Syntaxe
  • Cas particulier : Déclaration des membres de type Tableau
  • Sérialisation des membres d'une classe
  • Immuabilité des membres d'une classe
  • Data binding
  • Déclaration des constantes de la classe
  • Syntaxe
  • Détail de la syntaxe
  • Exemple
  • Création et déclaration d'un singleton
  • Création et déclaration des méthodes de classes
  • Création d'une méthode de classe
  • Syntaxe de déclaration d'une méthode
  • Détail de la syntaxe
  • Suppression d'une méthode
  • Création et déclaration des propriétés
  • Présentation
  • Création d'une propriété de classe
  • Data binding
  • Droits d'accès à une propriété
  • Membres et propriétés
  • Héritage
  • Passage de propriétés en paramètre à une fonction ou procédure WLangage
  • Instances de classe à contexte HFSQL indépendant
  • Présentation
  • Syntaxe
  • Utilisation
  • Notes
  • Légende des icônes utilisées
  • Nouveautés depuis la version 9
WINDEV
WindowsLinuxUniversal Windows 10 AppJavaEtats et RequêtesCode Utilisateur (MCU)
WEBDEV
WindowsLinuxPHPWEBDEV - Code Navigateur
WINDEV Mobile
AndroidWidget AndroidiPhone/iPadWidget IOSApple WatchMac CatalystUniversal Windows 10 App
Autres
Procédures stockées
Présentation d'une classe
Une classe est composée de :
  • données, appelées membres.
  • constantes.
  • procédures, appelées méthodes. Une méthode est une procédure spécialement écrite pour manipuler les objets de la classe.
  • propriétés. Une propriété est un élément de la classe qui s'utilise directement par son nom comme un membre et pour lequel les opérations d'affectation et de récupération de la valeur provoquent l'exécution d'un traitement.
Pour utiliser une classe, il faut déclarer un ou plusieurs objets. Tous les objets d'une classe donnée sont identiques par leur forme et leur comportement, mais leurs membres contiennent des données différentes.
Par défaut les membres d'une classe sont publics, ils sont accessibles aussi bien par une méthode de la classe que par un traitement/événement du projet ou de ses éléments (champ, fenêtre, ...).
Exemple de classe
La classe "CFichier" est composée des membres : m_sCheminCourt, m_sCheminLong, m_sExtension, m_sNomCourt, m_sNomLong.
La classe "CFichier" a les méthodes suivantes :
  • DateFichier()
  • SelectionFichier()
  • HeureFichier()
  • TailleFichier()
Cette classe n'a pas de propriétés.
Les informations affichées dans le volet "Explorateur de projet" sont les suivantes :
Explorateur de projet, dossier
Pour connaître la légende des différentes icônes utilisées, consultez les Notes.
Création et déclaration d'une classe

Création d'une classe

Pour créer une classe :
  1. Affichez si nécessaire le volet "Explorateur de projet" : sous le volet "Accueil", dans le groupe "Environnement", déroulez "Volets" puis sélectionnez "Explorateur de projet".
  2. Dans le volet "Explorateur de projet", affichez le menu contextuel du dossier "Classes" puis sélectionnez "Créer une classe".
  3. Saisissez le nom de la classe dans la fenêtre qui s'ouvre et validez.
  4. L'éditeur de code affiche le code de la nouvelle classe. L'événement "Déclaration" de la classe ainsi que le constructeur et le destructeur sont automatiquement créés.

Syntaxe de déclaration de la classe et de ses éléments

<NomClasse> est une Classe [, abstraite]
<Portée et droits>
<Déclaration membre 1>
<Déclaration membre 2>
<Portée et droits>
<Déclaration membre 3>
<Déclaration membre 4>
...
<CONSTANTE>
<Déclaration des constantes>
FIN
Déclaration d'une classe

Syntaxe

<NomClasse> est une Classe [, abstraite] [, immuable]
  ...
FIN
<NomClasse>
Nom identifiant la classe.
abstraite : optionnel
Permet d'indiquer que la classe est abstraite. Une classe abstraite est une classe de base qui regroupe des comportements communs à plusieurs classes.
Une classe est abstraite lorsqu'elle est déclarée comme telle ou si une de ses méthodes est abstraite.
Une classe abstraite ne peut pas être instanciée.
Nouveauté 2024
immuable : optionnel
Permet d'indiquer que tous les membres de la classe sont immuables. Dans ce cas, la valeur des membres immuables est définie soit lors de la déclaration du membre, soit dans le constructeur de la classe.

Exemple

ClasseSystème est une Classe
Nom est une chaîne
FIN
Déclaration des membres d'une classe

Syntaxe

[GLOBAL] [<Mode d'accès>]
<Nom du membre> est un <Type du membre> [ = <Valeur initiale>]
GLOBAL : Optionnel
Définit un membre global. Ce membre existera en dehors des objets. Il pourra être utilisé sans instancier un objet. Si plusieurs objets sont déclarés, un membre global est commun à tous les objets.
<Mode d'accès> : Optionnel
Permet de restreindre l'accès à ce membre de la classe.
  • Public (par défaut) : Accès autorisé depuis n'importe quel code de la classe ou du projet.
  • Public CONSTANT : La valeur du membre peut être lue et modifiée depuis un code de la classe ou d'une classe dérivée, et uniquement lue depuis un autre code de l'application.
  • Protégé : Accès autorisé depuis un code de la classe ou un code d'une classe dérivée (et "héritée")
  • Protégé CONSTANT : La valeur du membre peut être lue et modifiée depuis un code de la classe, uniquement lue depuis un code d'une classe dérivée, et inaccessible depuis un autre code de l'application.
  • Privé : Accès autorisé depuis un code de la classe.
<Nom du membre>
Nom identifiant le membre.
<Type du membre>
Type du membre choisi parmi les types disponibles du WLangage.
<Valeur initiale>
Valeur initiale du membre.
ClasseSystème est une Classe
Nom est une chaîne
GLOBAL PRIVÉ
TailleClasse est un entier
FIN

Cas particulier : Déclaration des membres de type Tableau

Pour déclarer un tableau dans une classe, il suffit d'utiliser la syntaxe suivante :
ClasseSystème est une Classe
TableauDéfaut est un tableau de 1 entier
FIN
Le tableau est déclaré de la même façon que les tableaux simples (pour plus de détails, consultez le type Tableau).
Lors de copies d'instances de classes, tous les membres de la classe sont recopiés dans la nouvelle instance, sauf les tableaux. Ainsi, si la valeur d'un membre de type tableau est modifiée, cette valeur est modifiée dans toutes les instances.
Pour obtenir des tableaux indépendants dans toutes les instances de classes, il est nécessaire de déclarer un tableau local de la manière suivante :
ClasseSystème est une Classe
TableauDéfaut est un tableau local de 1 entier
FIN

Remarque : Pour obtenir des tableaux indépendants dans toutes les instances de classes :
  1. Affichez la fenêtre de description du projet : sous le volet "Projet", dans le groupe "Projet", cliquez sur "Description".
  2. Dans l'onglet "Compilation", cochez l'option "Tableaux : l'affectation copie le contenu".
Pour plus de détails, consultez Description projet, onglet compilation.

Sérialisation des membres d'une classe

Par défaut, tous les membres d'une classe sont sérialisés.
Il est possible de gérer précisément la sérialisation de chaque membre d'une classe :
  • en indiquant quel membre sera sérialisé lors de l'appel à la fonction Sérialise.
    Cette opération est possible sur tous les types de sérialisation (WXML, JSON, binaire).
  • en changeant le nom du membre lors de la sérialisation par la fonction Sérialise.
    Cette opération n'est pas possible lors d'une sérialisation binaire.
Cette gestion de la sérialisation est réalisée en utilisant la syntaxe suivante :
  • Sérialisation ou non d'un membre :
    <Nom du membre> est un <Type du membre> [ = <Valeur initiale>]
    [, Sérialise = <Vrai/Faux>]
  • Sérialisation et changement du nom d'un membre :
    <Nom du membre> est un <Type du membre> [ = <Valeur initiale>]
    [, Sérialise = <Nouveau nom>]
Exemple :
Cl est une Classe
// Membre sérialisé
MembreSérialisé est un entier 
// Membre non sérialisé
MembreNonSérialisé est une chaîne, sérialise = faux  
// Membre renommé lors de la sérialisation
MembreRenommé est un entier, sérialise = "NouveauNomMembre" 
FIN
Nouveauté 2024

Immuabilité des membres d'une classe

Un membre de classe peut être immuable. Dans ce cas, lorsque sa valeur est définie, elle ne pourra pas changer. La valeur des membres immuables est définie soit lors de la déclaration du membre, soit dans le constructeur de la classe.
Pour définir l'immuabilité d'un membre, il est possible :
  • de spécifier l'immuabilité au niveau de la classe. Dans ce cas, tous les membres de la classe seront immuables.
  • de spécifier l'immuabilité au niveau du membre.
La syntaxe pour définir l'immuabilité d'un membre est la suivante :
<Nom du membre> est un <Type du membre> [ = <Valeur initiale>] [, immuable]
Exemple :
Cl est une Classe, immuable
Membre1 est entier = 5
id est un entier // id sera défini dans le constructeur
FIN
Cl est une Classe
Membre1 est entier, immuable = 5
id est un entier, immuable // id sera défini dans le constructeur
FIN

Data binding

Le Data binding est disponible sur les membres de la classe.
Déclaration des constantes de la classe

Syntaxe

CONSTANT <Nom de la constante> = <Valeur de la constante>

CONSTANT
<Nom de la constante> = <Valeur de la constante>
<Nom de la constante> = <Valeur de la constante>
FIN

Détail de la syntaxe

<Nom de la constante>
Nom défini pour la constante. Une constante est publique.
<Valeur de la constante>
Valeur associée à la constante. Cette valeur ne variera pas au cours du programme.

Exemple

CONSTANT K=5
CONSTANT 
K=5
J=10
FIN
Création et déclaration d'un singleton
Un Singleton est une déclaration d'une instance unique de classe.
Pour déclarer une instance unique d'une classe et pour l'allouer immédiatement, il est possible d'utiliser la syntaxe suivante :
<Nom classe singleton> est une Classe
GLOBAL
<Nom instance> est <Nom classe singleton>
FIN


Exemple
CSingleton est une Classe
GLOBAL
m_Singleton est CSingleton
FIN
Création et déclaration des méthodes de classes

Création d'une méthode de classe

Pour créer une méthode de classe :
  1. Affichez si nécessaire le volet "Explorateur de projet" : sous le volet "Accueil", dans le groupe "Environnement", déroulez "Volets" puis sélectionnez "Explorateur de projet"..
  2. Dans le volet "Explorateur de projet", affichez les différentes classes disponibles : il suffit de dérouler le dossier "Classes".
  3. Sélectionnez la classe voulue. Affichez le menu contextuel de la classe (clic droit) puis sélectionnez l'option "Nouvelle méthode".
  4. Dans la fenêtre qui s'ouvre :
    • Saisissez le nom de la méthode.
    • Indiquez si le commentaire du prototype de la méthode doit être généré automatiquement (option "Générer un commentaire d'en-tête").
      Pour plus de détails sur les commentaires générés automatiquement, consultez Documentation automatique des procédures et des méthodes.
    • Indiquez si la méthode est publique, protégée ou privée. Pour plus de détails, consultez la partie "Accès" du Détail de la syntaxe.
    • Indiquez si la méthode est abstraite. Pour plus de détails, consultez la partie "Abstraite" du Détail de la syntaxe.
    • Indiquez si la méthode est globale. Pour plus de détails, consultez la partie "Globale" du Détail de la syntaxe.
    • Validez.
  5. L'éditeur de code affiche le code de la nouvelle méthode.

Syntaxe de déclaration d'une méthode

PROCEDURE [<Accès>] [Globale] [VIRTUELLE] [ABSTRAITE]
<Nom de la méthode> ([<Paramètre1>, ...[<ParamètreN>]]) [<Attributs d'extension>]

Détail de la syntaxe

<Accès> : Optionnel
Permet de restreindre l'accès à cette méthode. 3 niveaux sont disponibles :
  • Privé : la méthode peut être appelée uniquement depuis un code de la classe
  • Protégé : la méthode peut être appelée uniquement depuis un code de la classe ou un code d'une classe dérivée
  • Public (par défaut) : la méthode peut être appelée depuis n'importe quel code de la classe ou du projet.
Globale : Optionnel
Définit une méthode globale. Cette méthode ne travaillera pas sur un objet particulier : il n'est pas nécessaire de disposer d'un objet de la classe pour appeler cette méthode. Cette classe permet aussi de manipuler les membres globaux.
Virtuelle : Optionnel
Définit une méthode virtuelle. Par défaut, une méthode redéfinie est virtuelle.
Abstraite : Optionnel
Définit une méthode abstraite. Une méthode abstraite est une méthode qui doit obligatoirement être redéfinie dans les classes dérivées. Par défaut, une méthode n'est pas abstraite.
<Nom de la méthode>
Nom identifiant la méthode.
<Paramètre 1> ... <Paramètre N>
Paramètres optionnels à passer à la méthode.
<Attribut d'extension>
Attributs d'extension permettant de définir des options de gestion de l'éditeur de code. Les attributs d'extension disponibles sont :
  • <zombie [commentaire = "texte"]> : Permet de définir une méthode obsolète (également appelée méthode zombie). Le mot-clé optionnel commentaire permet d'indiquer le texte qui sera affiché dans l'erreur de compilation associée à la méthode obsolète. Pour plus de détails, consultez Procédures zombies.
  • <sans pas à pas> : Permet d'indiquer que cette méthode sera ignorée par le débogueur lors d'un débogage en mode "Pas à pas".
PROCÉDURE GLOBALE VoirObjet(obj)
// Le membre privé TailleClasse est accessible depuis le code de la classe
Info("Nom : " + obj:Nom + "Taille : " + obj:TailleClasse)
FONCTION GLOBALE Essai(a1,b1)
RENVOYER a1 + b1

Suppression d'une méthode

Une méthode peut être supprimée :
  • directement depuis le volet "Explorateur de projet" (option "Supprimer" du menu contextuel)
  • depuis l'éditeur de code, par le menu contextuel du bandeau de la méthode (option "Supprimer").
Création et déclaration des propriétés

Présentation

Une propriété est un élément de code possédant deux événements :
  • un événement de récupération de la valeur,
  • un événement d'affectation de la valeur.
Une propriété peut être utilisée comme une variable ou un membre (récupération directe de la valeur, affectation par le symbole '=', ...). Lors de l'exécution :
  • Toute opération nécessitant la lecture de la propriété exécute l'événement de récupération de la valeur. Cet événement doit renvoyer une valeur.
  • Toute opération nécessitant l'écriture de la propriété exécute l'événement d'affectation de la valeur. Cet événement doit traiter un paramètre.

Création d'une propriété de classe

Pour créer une propriété de classe :
  1. Affichez si nécessaire le volet "Explorateur de projet" : sous le volet "Accueil", dans le groupe "Environnement", déroulez "Volets" puis sélectionnez "Explorateur de projet".
  2. Dans le volet "Explorateur de projet", affichez les différentes classes disponibles (déroulez le dossier "Classes").
  3. Sélectionnez la classe voulue. Affichez le menu contextuel de la classe et sélectionnez l'option "Nouvelle propriété".
  4. Saisissez le nom de la propriété dans la fenêtre qui s'ouvre et validez.
  5. L'éditeur de code affiche les événements liés à la propriété :
    • Evénement de récupération de la propriété. Cet événement contient :
      • soit le mot-clé "RENVOYER" qui permet d'obtenir la valeur de la propriété.
      • soit le mot-clé "RETOUR =" pour renvoyer la valeur de la propriété.
    • Evénement d'affectation de la propriété. Cet événement permet de donner une valeur à la propriété. Cette valeur est passée en paramètre. Cet événement ne doit pas renvoyer de résultat.
Remarque : Une nouvelle propriété peut également être créée depuis le menu contextuel d'un membre. Les procédures manipulent alors automatiquement le membre spécifié.

Data binding

Le Data binding est disponible sur les propriétés des classes et des membres de classes.

Droits d'accès à une propriété

Si l'événement de récupération est vide, la lecture de la propriété est interdite. Une erreur de compilation apparaîtra sous l'éditeur et une erreur se produira également en exécution.
Si l'événement d'affectation est vide, l'écriture de la propriété est interdite. Une erreur de compilation apparaîtra sous l'éditeur et une erreur se produira également en exécution.
Les événements de récupération et d'affectation peuvent être publics, privés ou protégés. Les droits d'accès de la propriété correspondent aux droits les moins restrictifs des deux événements. Pour plus de détails, consultez Droits d'accès à une propriété.
Les propriétés peuvent être globales. Une propriété est globale à la classe lorsque les événements de récupération et d'affectation sont globaux. Si l'un des événements est global, tous les événements doivent l'être sinon une erreur de compilation est affichée.

Membres et propriétés

Une propriété peut avoir le même nom qu'un membre déjà existant. Dans ce cas, les ordres de priorité sont les suivants :
  • dans les événements de la propriété, le membre est prioritaire sur la propriété.
  • dans tout le reste du code, la propriété est prioritaire sur le membre.
Ainsi, il est possible de remplacer un membre par une propriété sans aucune modification du code utilisant le membre.
Les événements d'une propriété ne peuvent pas utiliser récursivement la propriété. S'il n'existe pas de membre du même nom que la propriété, l'utilisation de la propriété dans un de ses événements provoquera une erreur de compilation.

Héritage

Les propriétés des classes de base sont héritées dans les classes dérivées.
Une propriété peut être surchargée dans une classe dérivée. Les événements d'une propriété sont toujours considérés comme virtuels : l'utilisation du mot-clé VIRTUEL est inutile et ignorée.
L'héritage multiple est supporté sur les propriétés. Il est possible d'appeler les propriétés des classes de base grâce aux syntaxes :
  • Ancêtre.Propriété si la classe dérivée n'a qu'une seule classe de base
  • ClasseDeBase.Propriété dans tous les cas.

Passage de propriétés en paramètre à une fonction ou procédure WLangage

Si le paramètre est passé par référence (cas par défaut) et non typé :
  • la propriété est passée en paramètre.
  • aucun événement associé à la propriété n'est exécuté au moment de l'appel.
  • la lecture du paramètre formel exécute le code de récupération de la valeur.
  • l'écriture du paramètre formel exécute le code d'affectation de la valeur.
Si le paramètre est passé par valeur (LOCAL) et non typé :
  • la valeur de la propriété est passée en paramètre.
  • le code de récupération de la valeur est exécuté au moment de l'appel.
  • la lecture du paramètre formel accède à la valeur passée au moment de l'appel et n'exécute pas le code de récupération de la valeur.
  • l'écriture du paramètre formel modifie la valeur passée au moment de l'appel et n'exécute pas le code d'affectation de la valeur.
Si le paramètre est passé par référence (cas par défaut) et typé :
  • la propriété est passée en paramètre.
  • le type de la propriété doit être correct. Dans le cas contraire, une erreur WLangage est affichée.
  • aucun événement associé à la propriété n'est exécuté au moment de l'appel.
  • la lecture du paramètre formel exécute le code de récupération de la valeur.
  • l'écriture du paramètre formel exécute le code d'affectation de la valeur.
Si le paramètre est passé par valeur (LOCAL) et typé :
  • la valeur de la propriété est passée en paramètre.
  • le code de récupération de la valeur est exécuté au moment de l'appel.
  • si nécessaire, la valeur de la propriété est convertie dans le type du paramètre.
  • la lecture du paramètre formel accède à la valeur passée au moment de l'appel et n'exécute pas le code de récupération de la valeur.
  • l'écriture du paramètre formel modifie la valeur passée au moment de l'appel et n'exécute pas le code d'affectation de la valeur.
Instances de classe à contexte HFSQL indépendant

Présentation

Il est possible d'associer une copie du contexte HFSQL à une instance de classe. Tous les accès à HFSQL effectués depuis les méthodes et les propriétés de la classe (appels de fonctions ou accès aux enregistrements) opèrent sur la copie du contexte de l'instance de la classe.

Syntaxe

La syntaxe à utiliser est la suivante :
// Déclaration de la classe
ClasseHFSQLIndépendant est une Classe, contexte HFSQL indépendant [<léger/complet>]
FIN
ou
// Déclaration de la classe
ClasseHFSQLIndépendant est une Classe
<contexte HFSQL indépendant léger/complet>

FIN
Par exemple :
ClasseHFSQLIndépendant est une Classe, contexte HFSQL indépendant léger
Paramètre léger/complet :
  • Le mot-clé "léger" provoque la copie immédiate d'une partie du contexte HFSQL.
    Seuls les répertoires où se trouvent les fichiers de données en HFSQL Classic et/ou les connexions en HFSQL Client/Serveur sont mémorisés.
  • Le mot-clé "complet" provoque la copie immédiate du contexte HFSQL.
    Conseillé par exemple si le thread doit tenir compte des positions en cours dans les fichiers et requêtes du contexte de l'appelant.

Utilisation

Le contexte HFSQL de l'instance est créé par copie du contexte courant lors de l'exécution du constructeur.
Les opérateurs = et <= entre deux instances à contexte HFSQL indépendant recopient le contenu du contexte HFSQL.
Il est déconseillé d'utiliser des instances de classes à contexte HFSQL indépendant pour simuler un alias sur un seul fichier HFSQL ou sur un enregistrement particulier d'un fichier HFSQL. La copie du contexte HFSQL porte en effet sur tous les éléments (les fichiers, vues, requêtes, connexions, ...) du contexte et peut donc être très coûteuse en temps.
Une instance de classe à contexte HFSQL indépendant peut être utilisée uniquement dans le thread qui a exécuté le constructeur. Pour manipuler une instance de classe à contexte HFSQL indépendant dans plusieurs threads, il est nécessaire :
  • d'allouer une nouvelle instance de la classe,
  • de faire une copie de l'instance d'origine grâce à l'opérateur = ou <=.
Notes

Légende des icônes utilisées

Les différentes icônes utilisées sont les suivantes :
Procédure publique
Procédure publique
Procédure protégée
Procédure protégée
Procédure privée
Procédure privée
Méthode virtuelle publique
Méthode virtuelle publique
Méthode virtuelle protégée
Méthode virtuelle protégée
Méthode virtuelle privée
Méthode virtuelle privée
Méthode globale publique
Méthode globale publique
Méthode globale protégée
Méthode globale protégée
Méthode globale privée
Méthode globale privée
Constante
Constante

Nouveautés depuis la version 9

Une classe contenant un membre de type caractère n'a pas le même comportement que dans les versions précédentes. En effet, les caractères occupaient 1 octet dans les versions précédentes et 2 octets à partir de la version 9.
Il est conseillé d'utiliser le type "Entier sur un octet" pour assurer un bon fonctionnement.
Liste des exemples associés :
WD POO Simple Exemples didactiques (WINDEV) : WD POO Simple
[ + ] L'exemple "WD POO Simple" est un exemple didactique sur la POO avec WINDEV. Cet exemple permet de voir le fonctionnement :
- des classes,
- des héritages,
- des procédures virtuelles,
- des diagrammes UML,
- ...
Version minimum requise
  • Version 10
Documentation également disponible pour…
Commentaires
Pattern Singleton
J'ai trouvé qu'un pattern Singeton paresseux est en général meilleur, notamment pour éviter des dépendances cycliques entre classes à l'initialisation (surtout qu'on ne peut pas contrôler l'ordre dans lequel les classes sont chargées)

Je le déclare en gros comme ceci

MaClasse est une Classe
// Instance
PRIVE GLOBAL
gSingleton est un MaClasse dynamique
FIN

// Propriété
PUBLIQUE GLOBAL Obj() : MaClasse
SI ::gSingleton = null ALORS
::gSingleton = new MaClasse()
FIN

RENVOYER ::gSingleton
FIN
Antoine MARQUES
20 avr. 2018

Dernière modification : 25/09/2023

Signaler une erreur ou faire une suggestion | Aide en ligne locale