septembre
2013
Modification apportée le 11.12.2013 grâce à une précision de zechatdoc.
L’Héritage c’est quoi ?
- Utiliser les champs hérités de la classe de base ( selon leur visibilité).
- Ajouter des nouveaux champs.
- Utiliser une méthode héritée ( selon la visibilité).
- Redéfinir une méthodes en la créant avec la même signature.
- Surcharger une méthode en la créant avec un signature différente.
- Ajouter une nouvelle méthode.
- Ajouter un ou plusieurs constructeur.
L’héritage par Windev par l’exemple
- Définition de l’exemple
- Constructeur sans paramètre
- Programme principale
- Constructeur avec paramètres.
-
Pour évoquer la notion d’héritage en Windev, je vais créer deux classes
ac_voiture : Classes pseudo abstraite (Cf un futur article sur les classes abstraites en windev) représentant une voiture.
pc_peugeot : Classes héritant de ac_voiture représentant une voiture de marque « Peugeot ».
Membres de la classe ac_voiture
ls_marque est une chaîne
ls_modele est une chaîne
GLOBALE
li_nbVoiture est un entier
Les membres ont des propriétés en lecture/éciture
PROCEDURE Marque() //Lecture
RENVOYER :ls_marque
PROCEDURE Marque(ps_marque est une chaîne) //Ecriture
:ls_marque = ps_marque
PROCEDURE Modele() //Lecture
RENVOYER :ls_modele
PROCEDURE Modele(ps_modele est une chaîne) //Ecriture
:ls_modele = ps_modele
Membres de la classe pc_peugeot
PRIVÉE
lb_moteurHdi est un booléen
Le membre a des propriétés en lecture/écriture
RENVOYER :lb_moteurHdi
PROCEDURE moteurHdi(pb_moteurHdi est un booléen) //Ecriture
:lb_moteurHdi = pb_moteurHdi
Constructeur ac_voiture
//---->Pas de code
Constructeur pc_peugeot
Ancêtre:Constructeur()
Dans le code d’initialisation de la fenêtre je vais instancier un objet de type pc_peugeot.
Constructeur de la classe ac_voiure
:ls_marque=ps_marque
:ls_modele=ps_modele
Constructeur de la classe pc_peugeot
Ancêtre:Constructeur(ps_marque,ps_modele)
:lb_moteurHdi=pb_hdi
Au niveau de mon code principal, j’effectue certaines modification :
Le code se compile, mais j’ai une erreur lors de l’exécution.
Erreur à la ligne 0 du traitement Constructeur de la classe pc_peugeot.
Les paramètres d’appel du code ‘Constructeur de la classe ac_voiture’ sont incorrects : on attendait 2 paramètres et on en a reçu 0.
Apres quelques recherches, j’ai isolé la ligne de code qui posait problème
hérite de ac_voiture
:ls_marque=ps_marque
:ls_modele=ps_modele
Trace("Marque : "+:ls_marque+" - Modele : "+:ls_modele)
Trace("Marque : "+:ls_marque+" - Modele : "+:ls_modele)
Le résultat de la trace
Marque : – Modele :
Marque : Peugeot – Modele : 308
Conséquences …
PROCEDURE PROTÉGÉ Constructeur()
//---->Pas de code
PROCEDURE Constructeur()
Ancêtre:Constructeur()
Rappel : Les membres statiques sont des champs ou méthodes qui sont accessibles par la classe elle même ou par toutes les instances de la classe. on parle également de membres partagés. Ils son très utiles lorsque vous avez à gérer dans une classe des informations qui ne sont pas spécifique à une instance de classe mais à la classe elle même.
Classe ac_voiture
Ajout du membre statique li_nbvoiture, déclaration de la classe
PROTÉGÉE
ls_marque est une chaîne
ls_modele est une chaîne
GLOBALE
li_nbVoiture est un entier
FIN
Propriété en lecture pour le membre li_nbVoiture
RENVOYER ::li_nbVoiture
Modification du constructeur (Par défaut) pour incrémenter le membre statique
::li_nbVoiture++
Classe pc_peugeot
Ajout du membre statique li_nbPeugeot
pc_peugeot est une Classe
hérite de ac_voiture
PRIVÉE
lb_moteurHdi est un booléen
GLOBALE
li_nbPeugeot est un entier
FIN
Propriété en lecture pour le membre li_nbPeugeot
RENVOYER ::li_nbPeugeot
Modification du constructeur (Par défaut) pour incrémenter le membre statique
Ancêtre:Constructeur()
::li_nbPeugeot++
Nous venons de terminer l’ajout des membres statiques à nos classes, maintenant nous allons modifier le code principale pour avoir afficher dans une trace le nombre de voiture et le nombre de peugeot instancié.
Trace("Voiture : "+pc_peugeot.NbVoiture+" - Peugeot : "+pc_peugeot.nbPeugeot)
Résultat de la trace :
Voiture : 2 – Peugeot : 1
J’obtiens 2 voitures dont une Peugeot alors que je n’ai instancier qu’un seul objet.
Voila une des conséquences des appels prématurés automatiques, les données du programme sont erronées.
Ensuite je vais aussi insister sur le faite que nous sommes obligés d’avoir un constructeur par défaut dans la classe de base pour pouvoir mettre en place un héritage.
La subtilité
par
et supprimer le constructeur par défaut de ac_coiture
Merci zechatdoc pour m’avoir donner cette précision, même si pour moi la programmation est exactement la même en therme d’approche mais le résultat diffère et devient juste.
Conclusion
4 Commentaires + Ajouter un commentaire
Commentaires récents
- Héritage en WinDev : BUG ou subtilité du W-langage??? dans
- Héritage en WinDev : BUG ou subtilité du W-langage??? dans
- Héritage en WinDev : BUG ou subtilité du W-langage??? dans
- Héritage en WinDev : BUG ou subtilité du W-langage??? dans
- Windev : Norme de programmation pour les procédures et les champs graphiques dans
J’ai peut-être une piste pour ton interrogation.
Prenons un cas simple de classe si tu fais:
[quote]
pclTest est un CTest dynamique
pclTest : procedureA ()
[/quote]
Windev te diras gentiment que ce n’est pas possible car pclTest n’est pas allouer il faut :
[quote]
pclTest est un CTest dynamique
pclTest = new CTest ()
pclTest : procedureA ()
[/quote]
Alors que
[quote]
clTest est un CTest ()
pclTest : procedureA ()
[/quote]
Windev exécuteras la code de la procédure sans souci.
Revenons à notre cas d’héritage :
[quote]
Ancêtre : Constructeur ()
[/quote]
Si l’on regarde notre exemple d’avant cette syntaxe implique que ancêtre doit déjà allouer donc lors de la compilation Windev allouer avec le constructeur par default avant d’exécuter ce code. Cela correspond a :
[quote]
Ancêtre est un CTest ()
Ancêtre : Constructeur () // Soit il reconstruit l’objet Ancêtre si je peux me permettre
[/quote]
Alors que quand tu fais :
[quote]
Constructeur Ancêtre ()
[/quote]
Lors de la compilation Windev interprétera comme ceci est donc n’alloueras pas une première fois l’objet hérité :
[quote]
Ancêtre est un CTest ()
[/quote]
J’espère que cette explication est assez compréhensible si ce n’est pas le cas n’hésite pas a me le dire !
Bon développement à vous.
TArigault
PS: Je m’excuse des possibles et plus que probable fautes d’orthographes
Si on met rien, le compilateur ajoute automatiquement un appel au constructeur de la classe ancêtre. Il faut lui faire comprendre que la, on ne veut pas qu’il ajoute son appel car nous nous en chargeons nous-meme, et pour cela il y a cette syntaxe vraiment particulière.
Ancêtre:Constructeur() est une syntaxe classique d’appel de n’importe qu’elle fonction de la classe ancêtre, et n’est donc pas interprété de la facon particuliere dont est intereprétée la 1ere syntaxe.
Maintenant a quoi peut servir Ancêtre:Constructeur.. j’ai pas d’idée la comme ca…
Peut-etre que dans certaines situations, on a besoin d’executer le code du constructeur de la classe derivée (instanciation de membres absents de l’ancêtre…etc) avant de RElancer le code constructeur de la classe ancêtre.
En tous cas, même si le code est exécuté plusieurs fois, il n’y aura toujours bien qu’une instance.
Bonjour,
L’aide dit :
« Si une classe de base ou un membre de type classe possède un constructeur, ce constructeur est automatiquement appelé sans paramètre. Il faut :
soit attribuer des valeurs par défaut aux paramètres du constructeur (de la classe de base ou du membre)
soit appeler explicitement le constructeur en lui passant les paramètres.
»
puis
« Les constructeurs explicites de la classe de base ou du membre doivent être appelés en première instruction du constructeur de la classe dérivée. »
En écrivant le code conformément à ce qu’essaye d’exprimer l’aide, on obtient pour le constructeur de pc_peugeot :
[code]
PROCEDURE Constructeur()
Constructeur ac_voiture()
::li_nbPeugeot++
[/code]
Effectivement je viens de tester la ligne de code Constructeur ac_voiture(), pour moi cette résolution fait parti des tours de passe passe Windevien. Je trouve anormal de devoir passer par une parade pour avoir ce type de programme qui fonctionne correctement. Après on peut jouer sur le faite que s’est marqué dans la documentation officielle mais je me pose la question en quoi la ligne :
est fausse, ou même en quoi elle diffère dans l’esprit à
.
Sauf que le résultat et le nombre d’appel au constructeur diffère…..
Merci pour votre précision