Le forum (ô combien francophone) des utilisateurs de Powerbuilder.
Pages: 1
Imaginez que vous avez tendrement fait grandir une jolie hierarchie de classe, que vous avez pensé a tout, que quand vous l'utilisez vous multipliez votre productivité par 15... Bref, vous etes fier...!
Et vla't'y pas que le boss engage un pti jeune bien motivé qui s'empresse de sous-classer telle ou telle de vos classe parce qu'il a rien compris, ou - pire - s'amuse a instancier une classe qui n'aurait pas du l'etre... Bref, il vous enerve, il fout le bordel...!
C'est parti...!
1. La classe abstraite
Pour rappel, une classe abstraite (java, .NET,...) est une classe qui ne peut etre instanciee. Pourquoi? Parce qu'elle n'existe que pour servir d'ancetre a d'autres classes p.ex., mais ne represente en rien une entite business reelle.
p.ex.: Soit dans un magasin d'animaux les classes chien et chat - qui representent bien des entites vendues - et la classe animal, qui leur sert d'ancetre commun, pour p.ex. gerer les liaisons aux fiches veterinaires dans une seule classe. Ca n'aurait aucun sens pourtant de pouvoir instancier la classe animal, qui ne represente aucune realite du systeme... et donc, cette classe "utilitaire" devrait etre abstraite!
L'intro est finie, passons a la demo:
forward global type n_animal from nonvisualobject end type end forward global type n_animal from nonvisualobject end type global n_animal n_animal ... event constructor; if populateerror(0,'') = 1 then if error.object = this.classname( ) then runtimeerror lrte_error lrte_error = create runtimeerror lrte_error.setmessage( 'Abstract class ' + this.classname( ) + ' should not be instantiated.' ) throw lrte_error end if end if end event
Le principe est simple: this.classname() renvoie le classname de la classe qu'on essaie de creer. Tandis que la petite pirouette via le populateerror ne sert qu'a recuperer le classname correspondant au constructor dans lequel on se trouve. J'aurais pu hard-coder "if this.classname() = 'n_animal'", mais ca oblige a maintenir le code si on renome cette classe...
Et donc, si j'essaie de creer une instance de "n_animal", le code place dans le constructeur de "n_animal" va lancer une runtimeerror, laquelle va me renvoyer a ma copie...
A noter qu'on peut evidemment se creer une runtimeerror toute speciale pour ca, genre "abstractinstantiationerror" qui peut elle meme se changer du message d'erreur, comme ca, on n'aura plus qu'a mettre:
forward ... if error.object = this.classname( ) then throw create abstractinstantiationerror end if ...
Encore plus propre!
Et voici que le nvo n_animal est devenu une classe que l'on ne peut instancier...
Donc, le code suivant renverra toujours une erreur, ce qui empechera la variable "ln_a" d'etre creee:
n_animal ln_a
ln_a = create n_animal
Par contre, si j'herite n_animal pour creer n_chien, je peux ecrire sans probleme:
n_animal ln_a
ln_a = create n_chien
Tadaaaa!!!
C'est magique, hein?
C'est rapide, pas chere, ca rend le code propre, et ca donne enfin une utilite a la fenetre "Clip" dans l'IDE PB...
2. La classe sealed
Pour rappel, une classe scellée (sealed en .NET) est une classe qu'on ne peut plus hériter. P.ex. si on veut fournir des classes utilitaires a quelqu'un, sans lui permettre d'accéder aux membres protected,...
Et bien, en PB, il n'y a qu'un caractere a remplacer par rapport au code ci-dessus... On devine?
CQFD
Voila, vous voila parés pour rendre encore plus robustes vos frameworks...
Si ca sert a au moins une personne, je serai content... Alors n'hesitez pas a me dire ce que vous en pensez!
Hors ligne
000 pépites pour cette astuce
Hors ligne
Wooo... j'en demandais pas tant...!
... Mais la meilleure des recompenses serait de n'utiliser ce pouvoir que pour faire le bien...
Hors ligne
Pages: 1