4D v16.3Méthodes projet |
|||||||||||||||||||||||
|
4D v16.3
Méthodes projet
|
Type de paramètre | Mode de passage | Commentaire |
Champ, variable ou expression de type scalaire (numérique, texte, date...) | par valeur | Peut être passé par référence à l'aide d'un pointeur, voir ci-dessous |
Champ, variable ou expression de type Objet | par référence | Voir exemple ci-dessous |
Variable ou expression de type Collection | par référence | |
Variable ou expression de type Pointeur | par référence | Voir Passer des pointeurs aux méthodes |
Tableau | Ne peut pas être passé directement en paramètre | Peut être passé par référence à l'aide d'un pointeur, voir Tableaux et pointeurs |
Table | Ne peut pas être passée directement en paramètre | Peut être passée par référence à l'aide d'un pointeur, voir Pointeurs |
Lorsque vous utilisez des champs, variables ou expressions de type scalaire en tant que paramètres de méthodes projets, seules des copies des valeurs sont passées.
Puisque $1, $2... sont des variables locales, elles ne sont définies qu’à l’intérieur de la sous-routine et sont effacées à la fin de son exécution. Pour cette raison, une sous-routine ne peut pas modifier, au niveau de la méthode appelante, la valeur réelle des champs ou des variables passé(e)s en paramètre. Par exemple :
` Voici une partie de la méthode MA METHODE
` ...
FAIRE QUELQUE CHOSE([Personnes]Nom) ` Admettons que [Personnes]Nom est égal à "william"
ALERT([Personnes]Nom)
` Voici le code de la méthode FAIRE QUELQUE CHOSE
$1:=Uppercase($1)
ALERT($1)
La boîte de dialogue d'alerte affichée par FAIRE QUELQUE CHOSE contiendra "WILLIAM" et celle affichée par MA METHODE contiendra "william". La méthode a modifié localement la valeur du paramètre $1, mais cela n'affecte pas la valeur du champ [Personnes]Nom passé en paramètre par la méthode MA METHODE.
Si vous voulez réellement que la méthode FAIRE QUELQUE CHOSE modifie la valeur du champ, deux solutions s'offrent à vous :
1. Plutôt que de passer le champ à la méthode, vous lui passez un pointeur :
` Voici une partie de la méthode MA METHODE
` ...
FAIRE QUELQUE CHOSE(->[Personnes]Nom) ` Admettons que [Personnes]Nom est égal à "william"
ALERT([Personnes]Nom)
` Voici le code de la méthode FAIRE QUELQUE CHOSE
$1->:=Uppercase($1->)
ALERT($1->)
Ici, le paramètre n'est pas le champ lui-même, mais un pointeur vers le champ. Ainsi, à l'intérieur de la méthode FAIRE QUELQUE CHOSE, $1 ne contient plus la valeur du champ mais un pointeur vers le champ. L'objet référencé par $1 ($1-> dans le code ci-dessus) est le champ lui-même. Par conséquent, la modification de l'objet référencé dépasse les limites de la sous-routine et le champ lui-même est affecté. Dans cet exemple, les deux boîtes de dialogue d'alerte afficheront "WILLIAM".
Pour plus d'informations sur les pointeurs, reportez-vous à la section Pointeurs.
2. Plutôt que la méthode FAIRE QUELQUE CHOSE “fasse quelque chose”, vous pouvez la réécrire de manière à ce qu'elle retourne une valeur :
` Voici une partie de la méthode MA METHODE
` ...
[Personnes]Nom:=FAIRE QUELQUE CHOSE([Personnes]Nom) ` Admettons que [Personnes]Nom est égal à "william"
ALERT([Personnes]Nom)
` Voici le code de la méthode FAIRE QUELQUE CHOSE
$0:=Uppercase($1)
ALERT($0)
Une sous-routine retournant une valeur est appelée une fonction. Ce point est traité dans les paragraphes suivants.
Lorsque vous utilisez des variables, expressions ou champs de type objet ou collection en tant que paramètres de méthodes projet, ce sont des références vers les données sources qui sont passées. Dans ce cas, $1, $2... ne contiennent pas les valeurs mais des références. Toute modification de la valeur des paramètres $1, $2... à l'intérieur de la sous-routine sera propagée partout où l'objet ou la collection source est utilisée. C'est le même principe que pour les pointeurs, excepté le fait que les paramètres $1, $2... n'ont pas besoin d'être déréférencés à l'intérieur de la sous-routine.
Par exemple :
//La méthode CreatePerson crée un objet et l'envoie en tant que paramètre
C_OBJECT($person)
$person:=New object("Name";"Smith";"Age";40)
ChangeAge($person)
ALERT(String(OB Lire($person;"Age")))
//La méthode ChangeAge ajoute 10 à l'attribut Age de l'objet reçu
C_OBJECT($1)
OB SET($1;"Age";OB Get($1;"Age")+10)
ALERT(String(OB Lire($1;"Age")))
Si vous exécutez la méthode CreatePerson, les deux messages d'alerte contiendront "50" car la même référence est traitée par les deux méthodes.
4D Server : Lorsque des paramètres sont passés entre des méthodes qui ne sont pas exécutées sur la même machine (lors de l'utilisation de l'option Exécuter sur serveur par exemple, voir Propriétés des méthodes projet), il n'est pas possible d'utiliser des références. Dans ce cas, ce sont des copies des paramètres objet ou collection qui sont envoyées au lieu de références.
Les méthodes peuvent retourner des valeurs. Une méthode qui retourne une valeur est appelée une fonction.
Les commandes de 4D ou de plug-ins qui retournent une valeur sont également appelées fonctions.
Par exemple, la ligne d’instruction suivante utilise une fonction intégrée, Length, qui retourne la longueur d’une chaîne. La valeur retournée par Length est placée dans une variable appelée MaLongueur :
MaLongueur:=Length("Comment suis-je arrivé là ?")
Toute sous-routine peut retourner une valeur. La valeur à retourner est placée dans la variable locale $0.
Par exemple, la fonction suivante, appelée Majuscules4, retourne une chaîne dont les quatre premiers caractères ont été passés en majuscules :
$0:=Uppercase(Substring($1;1;4))+Substring($1;5)
Voici un exemple qui utilise la fonction Majuscules4 :
NouvellePhrase:=Majuscules4("Bien joué.")
Dans ce cas, la variable NouvellePhrase prend la valeur “BIEN joué.”
Le retour de fonction, $0, est une variable locale à la sous-routine. Elle peut être utilisée en tant que telle à l'intérieur de la sous-routine. Par exemple, dans le cas de la méthode FAIRE QUELQUE CHOSE utilisée précédemment, $0 recevait d'abord la valeur de $1, puis était utilisée en tant que paramètre de la commande ALERT. Dans une sous-méthode, vous pouvez utiliser $0 comme n'importe quelle autre variable locale. C'est 4D qui retourne sa valeur finale (sa valeur courante au moment où la sous-routine se termine) à la méthode appelée.
Des méthodes projet peuvent s'appeler les unes les autres, et en particulier :
Cela s'appelle la récursivité. Le langage de 4D supporte pleinement la récursivité.
Examinons l'exemple suivant : vous disposez d'une table [Amis et relations] composée de l'ensemble de champs suivant (très simplifié) :
- [Amis et parents]Nom
- [Amis et parents]Enfant'Nom
Pour cet exemple, nous supposons que les valeurs des champs sont uniques (il n'existe pas deux personnes avec le même nom). A partir d'un nom, vous voulez écrire la phrase “Un de mes amis, Pierre, qui est le rejeton de Paul qui est le rejeton de Martine qui est le rejeton de Robert qui est le rejeton de Gertrude, fait cela pour gagner sa vie !” :
1. Vous pouvez procéder de la manière suivante :
$vsNom:=Request("Saisissez le nom :";"Pierre")
If(OK=1)
QUERY([Amis et parents];[Amis et parents]Nom=$vsNom)
If(Records in selection([Amis et parents])>0)
$vtHistoireComplète:="Un de mes amis, "+$vsNom
Repeat
QUERY([Amis et parents];[Amis et parents]Enfant'Nom=$vsNom)
$vlResultRecherche:=Records in selection([Amis et parents])
If($vlResultRecherche>0)
$vtHistoireComplète:=$vtHistoireComplète+" qui est le rejeton de "+[Amis et parents]Nom
$vsNom:=[Amis et parents]Nom
End if
Until($vlResultRecherche=0)
$vtHistoireComplète:=$vtHistoireComplète+", fait cela pour gagner sa vie !"
ALERT($vtHistoireComplète)
End if
End if
2. Vous pouvez également procéder ainsi :
$vsNom:=Request("Saisissez le nom :";"Pierre")
If(OK=1)
QUERY([Amis et parents];[Amis et parents]Nom=$vsNom)
If(Records in selection([Amis et parents])>0)
ALERT("Un de mes amis, "+Généalogie de($vsNom)+", fait cela pour gagner sa vie !")
End if
End if
en utilisant la fonction récursive Généalogie de suivante :
` Méthode projet Généalogie de
` Généalogie de ( Chaîne ) -> Texte
` Généalogie de ( Nom ) -> Partie de la phrase
$0:=$1
QUERY([Amis et parents];[Amis et parents]Enfant'Nom=$1)
If(Records in selection([Amis et parents])>0)
$0:=$0+" qui est le rejeton de "+Généalogie de([Amis et parents]Nom)
End if
Vous notez que la méthode Généalogie de s'appelle elle-même.
La première manière de procéder utilise un algorithme itératif. La seconde manière utilise un algorithme récursif.
Lorsque vous implémentez du code pour traiter des cas comme celui décrit ci-dessus, vous aurez toujours le choix entre écrire des méthodes utilisant des algorithmes itératifs ou récursifs. Généralement, la récursivité permet d'écrire du code plus concis, lisible et plus facilement modifiable, mais utiliser la récursivité n'est absolument pas obligatoire.
Dans 4D, la récursivité est typiquement utilisée pour :
Important : Les appels récursifs doivent toujours se terminer à un moment donné. Dans l'exemple ci-dessus, la méthode Généalogie de cesse de s'appeler elle-même lorsque la recherche ne trouve plus d'enregistrement. Sans ce test conditionnel, la méthode s'appellerait indéfiniment et 4D pourrait au bout d'un certain temps retourner l'erreur “La pile est pleine” car le programme n'aurait plus assez de place pour "empiler" les appels (ainsi que les paramètres et les variables locales utilisés dans la méthode).
Conditions et boucles
Méthodes
Présentation des méthodes base
Produit : 4D
Thème : Présentation du langage
4D - Langage ( 4D v16)
4D - Langage ( 4D v16.1)
4D - Langage ( 4D v16.2)
4D - Langage ( 4D v16.3)