4D v14.3Guide du typage |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
4D v14.3
Guide du typage
Guide du typage
Cette section décrit les principales causes de conflits de types sur les variables, ainsi que les manières de les éviter. Les conflits de types simples peuvent se résumer comme suit :
Le conflit de types le plus simple est celui pour lequel un même nom de variable désigne deux objets différents. Imaginez que dans une application, vous écriviez : LaVariable:=5 et que, quelque part ailleurs, dans la même application, vous écriviez : LaVariable:=Vrai Vous générez un conflit de types. Le remède est simple : renommez l’une des deux variables. Imaginez que dans une application, vous écriviez : LaVariable:=5 et que, quelque part ailleurs, dans la même application, vous écriviez : C_BOOLEEN(LaVariable) Le compilateur, peignant d’abord les directives de compilation, fera de LaVariable un Booléen mais lorsqu’il découvrira : LaVariable:=5 il signalera un conflit de types. Ici encore, le remède est simple : renommez votre variable ou modifiez la directive de compilation. L’utilisation de variables de types différents dans une expression génère des incohérences. Le compilateur signale très logiquement les incompatibilités. Prenons un exemple simple. Vous écrivez : vBooléen:=Vrai `Le compilateur déduit que vBooléen est de type Booléen Certaines fonctions renvoient des variables d’un type bien précis. L’affectation du résultat d’une de ces variables à une variable déjà typée différemment provoquera un conflit de types si vous ne faites pas attention. No_Ident:=Demander("Numéro d’identification") `No_Ident est de type Texte Vous générez ici un conflit de type sur la troisième ligne. Le remède consiste à contrôler le comportement de la variable. Dans certains cas, vous aurez à créer des variables intermédiaires d’un nom différent. Dans d’autres cas, comme celui-ci en particulier, vous pouvez structurer différemment votre méthode : Déclarer deux fois la même variable par deux directives de compilation différentes constitue, bien sûr, un retypage. Si, dans la même base, vous écrivez : le compilateur est confronté à un dilemme et vous demande quelles étaient vos intentions. Le remède est simple : renommez l’une des deux variables. Il ne faut pas oublier que le conflit de types pour une directive C_ALPHA peut surgir si vous modifiez la longueur maximale de la chaîne de caractères. Ainsi, si vous écrivez : le compilateur est dans une situation de conflit puisque dans la déclaration des variables de type Alphanumérique, il doit réserver un emplacement de taille adéquate. C_ALPHA(7;LaChaine) Note : Si vous aviez écrit deux fois C_ALPHA(7;LaChaine), c’est-à-dire : le compilateur l’accepterait tout à fait. C’est simplement redondant. Les conflits de types pour les variables locales sont absolument identiques aux conflits de types pour les variables process et interprocess, à ceci près que ces conflits se déroulent dans un espace plus restreint. $Temp:="Bonjour" et puis plus loin $Temp:=5 En revanche, vous pouvez écrire dans une méthode M1 : $Temp:="Bonjour" et dans une méthode M2 : $Temp:=5 Les conflits possibles pour un tableau ne portent jamais sur la taille du tableau. En mode compilé comme en mode interprété, les tableaux sont gérés dynamiquement. La taille d’un tableau peut varier au fil des méthodes et vous n’avez pas, bien sûr, à déclarer une taille maximale pour un tableau.
Si vous déclarez un tableau comme étant un tableau d’Entiers, il doit rester un tableau d’Entiers pour toute la base. Il ne pourra jamais contenir, par exemple, des éléments de type Booléen. TABLEAU ENTIER(LeTableau;5) le compilateur ne peut identifier pour vous le type de LeTableau. En version interprétée, il peut vous arriver de changer le nombre de dimensions d’un tableau. TABLEAU ENTIER(LeTableau1;10) En revanche, vous pouvez, évidemment, avoir dans la même application TABLEAU ENTIER(LeTableau1;10) Par ailleurs, vous pouvez parfaitement écrire : TABLEAU BOOLEEN(LeTableau;5) Comme vous pouvez le noter dans nos exemples, c’est le nombre de dimensions d’un tableau qu’on ne peut changer en cours d’application et non la valeur des dimensions du tableau. Note : Un tableau à deux dimensions est en fait un ensemble de plusieurs tableaux à une dimension. Pour plus de précisions, reportez-vous à la section Tableaux à deux dimensions. Les tableaux de chaînes fixes, aussi appelés tableaux Alpha, suivent la même règle que les variables Alphanumériques et pour les mêmes raisons. TABLEAU ALPHA(5;LeTableau;10) le compilateur détecte un conflit de longueur. Le remède est simple : comme dans les chaînes Alpha, vous déclarez la longueur maximale. Le compilateur gère automatiquement les longueurs inférieures. Lors de l’utilisation des commandes COPIER TABLEAU, LISTE VERS TABLEAU, TABLEAU VERS LISTE, SELECTION VERS TABLEAU, SELECTION LIMITEE VERS TABLEAU, TABLEAU VERS SELECTION, VALEURS DISTINCTES, vous pouvez, volontairement ou involontairement, être conduit à des changements de type d’éléments ou de nombre de dimensions, ou pour un tableau Alpha, à des changements de longueur de chaîne. Vous vous retrouverez donc dans un des trois cas cités précédemment. Si vous souhaitez compiler une base de données qui utilise des tableaux locaux (tableaux visibles uniquement par les méthodes qui les ont créés), il est nécessaire de les déclarer explicitement dans 4D avant de les utiliser. TABLEAU ENTIER($MonTableau;10) Les variables dessinées dans un formulaire, qu’il s’agisse d’une case à cocher ou d’une zone externe, sont toutes des variables soit process, soit interprocess.
Les variables suivantes sont considérées comme des Numériques par défaut :
Note : Les variables de type Règle, Cadran et Thermomètre seront toujours typées comme des Numériques, même si vous avez choisi l’option Entier long par défaut pour le type des boutons dans les Préférences. Pour ces variables, vous ne pouvez jamais vous trouver dans un conflit de types puisqu’elles ne peuvent avoir d’autres types que ce type-là, qu’on soit en interprété ou en compilé. Une zone de graphe a automatiquement le type Graphe (Entier long). Il ne peut jamais y avoir de conflit de type. Une zone externe est toujours un Entier long. Il ne peut jamais y avoir de conflit de types. Ces variables sont les suivantes :
Ces variables se divisent en deux catégories :
Si vous utilisez des pointeurs dans vos applications, vous avez pu profiter de la puissance et de la flexibilité de cet outil dans 4D. Le compilateur en conserve intégralement les avantages. LaVariable:=5,3 Dans ce cas de figure, votre pointeur dépointé est une variable Numérique. En affectant à cette variable une valeur booléenne, vous provoquez un conflit de types. Si vous avez besoin dans une même méthode d’utiliser les pointeurs pour des propos différents, prenez soin de définir votre pointeur : LaVariable:=5,3 Un pointeur n’a aucune existence propre. Il est toujours défini en fonction de l’objet qu’il représente. C’est pourquoi le compilateur ne peut pas détecter des conflits de types générés par une utilisation sans contrôle des pointeurs. Vous n’aurez donc pas, en cas de conflit, de message d’erreur durant la phase de typage ou celle de compilation. Le compilateur a besoin, au moment de la compilation, des définitions des commandes des plug-ins utilisées dans la base à compiler, c’est-à-dire du nombre et du type des paramètres de ces commandes. Les risques d’erreur de typage sont inexistants à partir du moment où le compilateur trouve effectivement dans l’application ce que vous avez déclaré. Certains plug-ins, par exemple 4D Write, utilisent des commandes qui provoquent l’appel implicite à des commandes 4D. Le dernier paramètre que vous passez à cette routine est le nom d’une méthode, que vous aurez vous-même écrite dans 4D. Cette méthode sera appelée par 4D Write chaque fois que l’événement attendu sera reçu et cette méthode recevra automatiquement les paramètres suivants :
Afin que le compilateur connaisse l’existence de ces paramètres et les prenne en compte, vous devez vous assurer qu’ils peuvent effectivement être typés, soit par une directive de compilation, soit parce que leur utilisation, suffisamment explicite, permet de déduire leur type. 4D permet de créer et de manipuler des composants. Un composant 4D est un ensemble d’objets 4D représentant une ou plusieurs fonctionnalité(s) groupée(s) dans un fichier de structure (appelé base matrice), qu’il est possible d’installer dans différentes bases (appelées bases hôtes). Un conflit de nom peut se produire lorsqu’une méthode projet partagée du composant a le même nom qu’une méthode projet de la base hôte. Dans ce cas, lorsque du code est exécuté dans le contexte de la base hôte, c’est la méthode de la base hôte qui est appelée. Ce principe permet de “masquer” une méthode du composant avec une méthode personnalisée (par exemple pour obtenir une fonctionnalité différente). Lorsque le code est exécuté dans le contexte du composant, c’est la méthode du composant qui est appelée. Un masquage est signalé par un warning lors de la compilation de la base hôte. Si deux composants partagent des méthodes du même nom, une erreur est générée au moment de la compilation de la base hôte. Pour plus d'informations sur les composants, reportez-vous au manuel Mode Développement. Les manipulations des variables locales suivent toutes les règles déjà énoncées. De même que toutes les autres variables, elles ne peuvent être retypées en cours de méthode.
Il n’est pas possible de retyper une variable. Il est, en revanche, tout à fait possible de faire pointer un pointeur successivement sur des variables de type différent.
$Taille:=Taille tableau($1->) Dans la méthode ci-dessus, il y a changement de type de $0 suivant les valeurs de $1. Fonction OccupMém en mode interprété et compilé (exemple pour Macintosh)Ecrivons maintenant cette méthode en utilisant un pointeur : $Taille:=Taille tableau($1->) Il faut noter la différence entre ces deux séquences :
Le compilateur gère la puissance et la souplesse de l’indirection sur les paramètres. En mode interprété, 4D vous donne toute latitude concernant le nombre et le type des paramètres. Vous gardez en mode compilé cette même liberté à condition de ne pas introduire de conflit de types et de ne pas utiliser, dans la méthode appelée, plus de paramètres que vous en avez passés, ce qui est facile. Illustrons notre propos par un exemple : écrivons une fonction qui prend des valeurs, fait leur somme et renvoie cette somme formatée suivant un format qui peut varier avec les valeurs. Résultat:=LaSomme("##0,00";125,2;33,5;24) La méthode appelante récupérera dans ce cas la chaîne : 182,70, somme des nombres passés, formatée suivant le format spécifié. D’après ce que l’on a vu plus haut, les paramètres de la fonction doivent être passés dans un ordre précis : le format d’abord et ensuite les valeurs, dont le nombre peut varier d’un appel à l’autre. Examinons maintenant la fonction que nous appelons LaSomme : $Somme:=0 Cette fonction pourra être appelée de diverses manières : Résultat:=LaSomme("##0,00";125,2;33,5;24) De même que pour les autres variables locales, la déclaration du paramètre générique par directive de compilation n’est pas obligatoire. Si elle est nécessaire (cas d’ambiguïté ou d’optimisation), elle se fait avec la syntaxe suivante : C_ENTIER(${4}) La commande ci-dessus signifie que tous les paramètres à partir du quatrième (inclus) seront adressés par indirection. Ils seront tous de type Entier. Les types de $1, $2 et $3 pourront être quelconques. En revanche, si vous utilisez $2 par indirection, le type utilisé sera le type générique. Il sera donc de type Entier, même si pour vous, par exemple, il était de type Réel. Note : Le compilateur utilisant cette commande durant le typage, le nombre, dans la déclaration, doit toujours être une constante et jamais une variable. Des variables et des constantes de 4D ont un type et une identité fixés par le compilateur. On ne peut donc créer une nouvelle variable, une méthode, une fonction ou une commande de plug-in portant le nom d’une de ces variables ou d’une de ces constantes. Bien entendu, vous pouvez tester leur valeur et les utiliser comme auparavant. Voici la liste complète des Variables système de 4D accompagnées de leur type.
Lorsqu’on crée une colonne calculée dans un état, 4D crée automatiquement une variable C1 pour la première, C2, C3... pour les autres. Généralement, cette création est faite de façon transparente pour vous. La liste des constantes prédéfinies de 4D peut être consultée dans ce manuel via la Liste des thèmes de constantes, vous pouvez également les visualiser dans l’Explorateur, en mode Développement. |
PROPRIÉTÉS
Produit : 4D VOIR AUSSI
Conseils d’optimisation UTILISATION DE L'ARTICLE
4D - Langage ( 4D v12.4) Parent de : Guide du typage ( 4D v11 SQL Release 6) |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||