Aller au contenu principal
Version: 19

Classes

Vue d’ensemble

Le langage 4D prend en charge le concept de classes. Dans un langage de programmation, l'utilisation d'une classe vous permet de définir le comportement d'un objet avec des propriétés et des fonctions associées.

Une fois qu'une classe utilisateur est définie, vous pouvez instancier des objets de cette classe n'importe où dans votre code. Chaque objet est une instance de sa classe. Une classe peut s'étendre à une autre classe avec le mot-clé extend, puis hériter de ses fonctions.

Les modèles de classe 4D et JavaScript sont similaires, et basés sur une chaîne de prototypes.

Par exemple, vous pouvez créer une classe Person avec la définition suivante :

//Class: Person.4dm
Class constructor($firstname : Text; $lastname : Text)
This.firstName:=$firstname
This.lastName:=$lastname

Function sayHello()->$welcome : Text
$welcome:="Hello "+This.firstName+" "+This.lastName

Dans une méthode, créons une "Personne" :

var $person : cs.Person //object of Person class  
var $hello : Text
$person:=cs.Person.new("John";"Doe")
// $person:{firstName: "John"; lastName: "Doe" }
$hello:=$person.sayHello() //"Hello John Doe"

Gestion des classes

Définition d'une classe

Une classe utilisateur dans 4D est définie par un fichier de méthode spécifique (.4dm), stocké dans le dossier /Project/Sources/Classes/. Le nom du fichier est le nom de la classe.

Lorsque vous nommez des classes, gardez à l'esprit les règles suivantes :

  • Un nom de classe doit être conforme aux règles de nommage des propriétés.
  • Les noms de classe sont sensibles à la casse.
  • Il n'est pas recommandé de donner le même nom à une classe et à une table de base de données, afin d'éviter tout conflit.

Par exemple, si vous souhaitez définir une classe nommée "Polygon", vous devez créer le fichier suivant :

  • Dossier Project
    • Project
      • Sources
        • Classes
          • Polygon.4dm

Supprimer une classe

Pour supprimer une classe existante, vous pouvez :

  • sur votre disque, supprimer le fichier de classe .4dm du dossier "Classes",
  • dans l'Explorateur 4D, sélectionner la classe et cliquer sur ou choisir Déplacer vers la corbeille dans le menu contextuel.

Utiliser l'interface 4D

Les fichiers de classe sont automatiquement stockés à l'emplacement approprié lorsqu'ils sont créés via l'interface de 4D, soit via le menu Fichier, soit via l'Explorateur.

Vous pouvez créer un nouveau fichier de classe pour le projet en sélectionnant Nouveau> Classe... dans le menu Fichier de 4D ou dans la barre d'outils.

Vous pouvez également utiliser le raccourci Ctrl+Maj+Alt+k.

Explorateur

Dans la page Méthodes de l'Explorateur, les classes sont regroupées dans la catégorie Classes.

Pour créer une nouvelle classe, vous pouvez :

  • sélectionnez la catégorie Classes et cliquez sur le bouton .
  • sélectionnez Nouvelle classe... dans le menu d'actions en bas de la fenêtre de l'Explorateur ou dans le menu contextuel du groupe Classes.
  • sélectionnez Nouveau> Classe... dans le menu contextuel de la page d'accueil de l'Explorateur.

Prise en charge du code de classe

Dans les différentes fenêtres 4D (éditeur de code, compilateur, débogueur, explorateur d'exécution), le code de classe est essentiellement géré comme une méthode projet avec quelques spécificités :

  • Dans l'éditeur de code :
    • une classe ne peut pas être exécutée
    • une fonction de classe est un bloc de code
    • Aller à définition... sur un objet membre permet de rechercher des déclarations de fonction de classe; par exemple, "$o.f()" donnera comme résultat de recherche "Function f".
    • Chercher les références... sur la déclaration de fonction de classe recherche la fonction utilisée comme membre d'objet; par exemple, "Function f" donnera comme résultat "$o.f()".
  • Dans l'explorateur d'exécution et le débogueur, les fonctions de classe sont affichées au format \<ClassName&#062 ; constructor ou \<ClassName&#062 ;.\<FunctionName>.

Class stores

Les classes disponibles sont accessibles depuis leurs class stores. Il existe deux class stores dans 4D :

  • cs pour le class store utilisateur
  • 4D pour le class store intégré

cs

cs -> classStore

ParamètresTypeDescription
classStoreobject<-Class store utilisateur utilisateurs pour le projet ou le composant

La commande cs retourne le class store utilisateur pour le projet ou le composant courant. Elle retourne toutes les classes utilisateur définies dans le projet ou le composant ouvert. Par défaut, seules les classes ORDA du projet sont disponibles.

Exemple

Vous souhaitez créer une nouvelle instance d'un objet de myClass :

$instance:=cs.myClass.new()

4D

4D -> classStore

ParamètresTypeDescription
classStoreobject<-Class store 4D

La commande 4D retourne le class store des classes 4D intégrées disponibles. Elle donne accès à des API spécifiques telles que CryptoKey.

Exemple

Vous souhaitez créer une nouvelle clé dans la classe CryptoKey :

$key:=4D.CryptoKey.new(New object("type";"ECDSA";"curve";"prime256v1"))

L'objet classe

Lorsqu'une classe est définie dans le projet, elle est chargée dans l'environnement de langage 4D. Une classe est un objet lui-même de la classe "Class". Un objet classe possède les propriétés et fonctions suivantes :

  • chaîne name
  • objet superclass (null si aucun)
  • fonction new(), permettant d'instancier les objets de la classe.

De plus, un objet classe peut référencer un objet constructor (facultatif).

Un objet de classe est un objet partagé et est donc accessible simultanément à partir de différents processus 4D.

Héritage

Si une classe hérite d'une autre classe (c'est-à-dire que le mot-clé Class extends est utilisé dans sa définition), la classe parente est sa superclass.

Lorsque 4D ne trouve pas de fonction ou de propriété dans une classe, il la recherche dans sa superclass; s'il ne la trouve pas, 4D continue la recherche dans la superclasse de la superclasse, et ainsi de suite, jusqu'à ce qu'il n'y ait plus de superclasse (tous les objets héritent de la superclasse "Object").

Mots-clés de classe

Des mots-clés 4D spécifiques peuvent être utilisés dans les définitions de classe :

  • Function <Name> pour définir les fonctions de classe des objets.
  • Class constructor pour définir les propriétés des objets.
  • Class extends <ClassName> pour définir l'héritage.

Function

Syntaxe

Function <name>({$parameterName : type; ...}){->$parameterName : type}
// code
note

There is no ending keyword for function code. The 4D language automatically detects the end of a function's code by the next Function keyword or the end of the class file.

Les fonctions de classe sont des propriétés spécifiques de la classe. Ce sont des objets de la classe 4D.Function.

Dans le fichier de définition de classe, les déclarations de fonction utilisent le mot-clé Function, et le nom de la fonction. Le nom de la fonction doit être conforme aux règles de nommage des propriétés.

Astuce : Si vous préfixez le nom d'une fonction par un trait de soulignement ("_"), elle ne sera pas proposée par les fonctionnalités d'auto-complétion dans l'éditeur de code 4D. Par exemple, si vous déclarez Function _myPrivateFunction dans MyClass, elle ne sera pas proposée dans l'éditeur de code lorsque vous tapez "cs.MyClass. ".

Immédiatement après le nom de la fonction, des paramètres peuvent être déclarés pour la fonction avec un nom et un type de données, y compris le paramètre de retour (facultatif). Par exemple :

Function computeArea($width : Integer; $height : Integer)->$area : Integer

Dans une fonction de classe, la commande This est utilisée comme instance d'objet. Par exemple :

Function setFullname($firstname : Text; $lastname : Text)
This.firstName:=$firstname
This.lastName:=$lastname

Function getFullname()->$fullname : Text
$fullname:=This.firstName+" "+Uppercase(This.lastName)

Pour une fonction de classe, la commande Current method name retourne : <ClassName>.<FunctionName>, par exemple "MyClass.myMethod".

Dans le code de l'application, les fonctions de classes sont appelées comme des méthodes membres des instances d'objets et peuvent recevoir des paramètres si besoin. Les syntaxes suivantes sont prises en charge :

  • utilisation de l'opérateur (). Par exemple, myObject.methodName("hello")
  • utilisation d'une méthode membre de la classe "4D.Function" :

Attention thread-safe : Si une fonction de classe n'est pas thread-safe et est appelée par une méthode ayant l'attribut "Can be run in preemptive process" :

  • le compilateur ne génère pas d'erreur (ce qui est différent par rapport aux méthodes standard),
  • une erreur est déclenchée par 4D uniquement au moment de l'exécution.

Paramètres

Les paramètres des fonctions sont déclarés via le nom du paramètre et son type, séparés par deux-points. Le nom du paramètre doit être conforme aux règles de nommage des propriétés. Les paramètres multiples (et leurs types) sont séparés par des points-virgules (;).

Function add($x; $y : Variant; $z : Integer; $xy : Object)

Si le type n'est pas fourni, le paramètre sera défini comme Variant.

Vous déclarez le paramètre de retour d'une fonction (optionnel) en ajoutant une flèche (->) et la définition du paramètre de retour après la liste des paramètres d'entrée. Par exemple :

Function add($x : Variant; $y : Integer)->$result : Integer

Vous pouvez également déclarer le paramètre de retour en ajoutant uniquement : type, auquel cas il sera automatiquement disponible via $0. Par exemple :

Function add($x : Variant; $y : Integer): Integer
$0:=$x+$y

La syntaxe 4D classique pour les paramètres de méthodes peut être utilisée pour déclarer les paramètres des fonctions de classes. Les deux syntaxes peuvent être mélangées. Par exemple :

Function add($x : Integer)
var $2; $value : Integer
var $0 : Text
$value:=$x+$2
$0:=String($value)

Exemple

// Class: Rectangle
Class constructor($width : Integer; $height : Integer)
This.name:="Rectangle"
This.height:=$height
This.width:=$width

// Définition de fonction
Function getArea()->$result : Integer
$result:=(This.height)*(This.width)
// Dans une méthode projet

var $rect : cs.Rectangle
var $area : Real

$rect:=cs.Rectangle.new(50;100)
$area:=$rect.getArea() //5000

Class constructor

Syntaxe

// Class: MyClass
Class Constructor({$parameterName : type; ...})
// code
note

There is no ending keyword for class constructor function code. The 4D language automatically detects the end of a function's code by the next Function keyword or the end of the class file.

Une fonction class constructor, qui accepte des paramètres, peut être utilisée pour définir une classe utilisateur.

Dans ce cas, lorsque vous appelez la fonction new(), le class constructor est appelé avec les paramètres optionnellement passés à la fonction new().

Pour une fonction class constructor, la commande Current method name retourne : <ClassName>:constructor, par exemple "MyClass.constructor".

Exemple

// Class: MyClass
// Class constructor of MyClass
Class Constructor ($name : Text)
This.name:=$name
// Dans une méthode projet
// Vous pouvez instancier un objet
var $o : cs.MyClass
$o:=cs.MyClass.new("HelloWorld")
// $o = {"name":"HelloWorld"}

Class extends \<ClassName>

Syntaxe

// Class enfant
Class extends <ParentClass>

Le mot-clé Class extends est utilisé dans une déclaration de classe pour créer une classe utilisateur "enfant" d'une autre classe utilisateur. La classe "enfant" hérite de toutes les fonctions de la classe "parente".

L'extension de classe doit respecter les règles suivantes :

  • Une classe utilisateur ne peut pas étendre une classe intégrée (sauf 4D.Object et les classes ORDA qui sont étendues par défaut pour les classes utilisateur).
  • Une classe utilisateur ne peut pas étendre une classe utilisateur d'un autre projet ou composant.
  • Une classe utilisateur ne peut pas s'étendre elle-même.
  • Il n'est pas possible d'étendre des classes de manière circulaire (i.e. "a" étend "b" qui étend "a").

La violation de ces règles n'est pas détectable par l'éditeur de code ou l'interpréteur, seul le compilateur et la fonction vérifier syntaxe retourneront une erreur dans ce cas.

Une classe étendue peut appeler le constructeur de sa classe parente en utilisant la commande Super.

Exemple

Cet exemple crée une classe nommée Square à partir d'une classe nommée Polygon.

//Class: Square

//path: Classes/Square.4dm

Class extends Polygon


Class constructor ($side : Integer)

// Appelle le constructeur de la classe parente avec les côtés
// fournies pour la largeur et la hauteur du Polygone
Super($side;$side)
// Dans les classes dérivées, Super doit être appelé
// avant que vous puissiez utiliser 'This'
This.name:="Square"

Function getArea()
C_LONGINT($0)
$0:=This.height*This.width

Super

Syntaxe

Super {( param{;...;paramN} )} {-> Object} 
ParamètresTypeDescription
parammixte->Paramètre(s) à passer au constructeur de la classe parente
Résultatobject<-Parent de l'objet

Le mot-clé Super permet d'appeler la superclass, i.e.

Super peut être utilisé de deux différentes manières :

  1. A l'intérieur du code de la fonction constructeur, Super est une commande qui permet d'appeler le constructeur de la superclass. Lorsqu'elle est utilisée dans une fonction constructeur, la commande Super est seule et doit être appelée avant que le mot-clé This soit utilisé.
  • Si tous les class constructors dans l'arbre des héritages ne sont pas appelés correctement, l'erreur -10748 et générée. Il est de la responsabilité du développeur 4D de s'assurer que tous les appels sont valides.
  • Si la commande This est appelée sur un objet dont les superclasses n'ont pas été construites, l'erreur -10743 est générée.
  • Si Super est appelée en dehors d'un contexte d'objet, ou sur un objet dont le constructeur de la superclasse a déjà été appelé, l'erreur -10746 est générée.
// dans la fonction constructor de myClass
var $text1; $text2 : Text
Super($text1) //appel du constructeur de la superclasse avec un paramètre text
This.param:=$text2 // utilisation d'un second param
  1. A l'intérieur d'une fonction de classe, Super désigne le prototype de la superclasse et permet d'appeler une fonction de la hiérarchie de superclasses.
Super.doSomething(42) //appelle la fonction "doSomething"   
//déclarée parmi les superclasses

Exemple 1

Cet exemple illustre l'utilisation de Super dans un class constructor. La commande est appelée pour éviter de dupliquer les parties du constructeur qui sont communes aux classes Rectangle et Square.

// Class: Rectangle
Class constructor($width : Integer; $height : Integer)
This.name:="Rectangle"
This.height:=$height
This.width:=$width


Function sayName()
ALERT("Hi, I am a "+This.name+".")

// Function definition
Function getArea()
var $0 : Integer
$0:=(This.height)*(This.width)
//Class: Square

Class extends Rectangle

Class constructor ($side : Integer)

// Appelle le constructeur de la classe parente avec les côtés
// fournies pour la largeur et la hauteur du Rectangle
Super($side;$side)
// Dans les classes dérivées, Super doit être appelé
// avant que vous puissiez utiliser 'This'
This.name:="Square"

Function getArea()
C_LONGINT($0)
$0:=This.height*This.width

Exemple 2

Cet exemple illustre l'utilisation de Super dans une fonction de classe. Vous avez créé la classe Rectangle contenant une fonction :

//Class: Rectangle

Function nbSides()
var $0 : Text
$0:="I have 4 sides"

Vous avez également créé la classe Square contenant une fonction qui appelle la fonction superclass :

//Class: Square

Class extends Rectangle

Function description()
var $0 : Text
$0:=Super.nbSides()+" which are all equal"

Vous pouvez donc écrire dans une méthode projet :

var $square : Object
var $message : Text
$square:=cs.Square.new()
$message:=$square.description() //I have 4 sides which are all equal

This

Syntaxe

This -> Object
ParamètresTypeDescription
Résultatobject<-Objet courant

Le mot-clé This retourne une référence vers l'objet en cours de traitement. Dans 4D, il peut être utilisé dans différents contextes.

Dans la plupart des cas, la valeur de This est déterminée par la manière dont une fonction est appelée. Elle ne peut pas être définie par affectation lors de l'exécution, et elle peut être différente à chaque fois que la fonction est appelée.

Lorsqu'une formule est appelée en tant que méthode membre d'un objet, son This désigne l'objet sur lequel la méthode est appelée. Par exemple :

$o:=New object("prop";42;"f";Formula(This.prop))
$val:=$o.f() //42

Lorsqu'une fonction class constructor est utilisée (avec la fonction new()), son This désigne le nouvel objet en cours de construction.

//Class: ob

Class Constructor

// Créer des propriétés en
// les assignant au This
This.a:=42
// dans une méthode 4D  
$o:=cs.ob.new()
$val:=$o.a //42

En cas d'appel de la superclasse du constructeur depuis le constructeur en utilisant le mot-clé Super, n'oubliez pas que This ne doit pas être appelé avant le constructeur de la superclasse, sinon une erreur est générée. Voir cet exemple.

Dans tous les cas, This se réfère à l'objet sur lequel la fonction a été appelée, comme s'il s'agissait d'une fonction de l'objet.

//Class: ob

Function f()
$0:=This.a+This.b

Vous pouvez donc écrire dans une méthode projet :

$o:=cs.ob.new()
$o.a:=5
$o.b:=3
$val:=$o.f() //8

Dans cet exemple, l'objet affecté à la variable $o n'a pas de propriété f, il hérite de celle de sa classe. Comme f est appelée comme une méthode de $o, son This se réfère à $o.

Commandes de classes

Plusieurs commandes du langage 4D se rapportent à la manipulation des classes.

OB Class

OB Class ( object ) -> Object | Null

OB Class retourne la classe de l'objet passé en paramètre.

OB Instance of

OB Instance of ( object ; class ) -> Boolean

OB Instance of retourne true si object appartient à la class ou à l'une de ses classes héritées, et false sinon.