Programmation orientée objet en CodeFR
CodeFR propose un support simple de la programmation orientée objet grâce aux mots-clés Classe, Nouveau et Soi. Une classe regroupe des champs (les données) et des méthodes (le comportement) sous un même nom, et Nouveau permet de créer des objets (aussi appelés instances) à partir de cette classe.
Ce support reste volontairement simple : il n'y a pas d'héritage, pas de modificateurs de visibilité (public/privé) et pas de surcharge de méthodes. Tous les champs et toutes les méthodes sont accessibles partout — voir la section Limites actuelles en fin de page.
1. Déclarer une classe
Une classe se déclare avec Classe ... FinClasse, avant le bloc Debut ... Fin du programme. Elle contient des champs (déclarés avec Variable, comme d'habitude) et des méthodes (déclarées avec Fonction ... FinFonction, exactement comme une fonction classique).
Syntaxe
Classe NomClasse
Variable champ1: Type1
Variable champ2: Type2
Fonction NomMethode(param: Type)
// Instructions
FinFonction
FinClasse
Exemple
Classe Personne
Variable nom: Chaine
Variable age: Entier
Fonction SePresenter()
Ecrire("Je suis ", Soi.nom, ", j'ai ", Soi.age, " ans.\n")
FinFonction
FinClasse
2. Le constructeur
Il n'existe pas de mot-clé dédié pour le constructeur : il s'agit simplement d'une méthode nommée exactement Constructeur. Elle est appelée automatiquement lors de la création d'un objet avec Nouveau, et sert à initialiser les champs. Un constructeur ne peut pas déclarer de type de retour.
Si aucune méthode Constructeur n'est définie et que Nouveau est appelé sans argument, les champs prennent simplement leur valeur par défaut habituelle (0 pour Entier, "" pour Chaine, etc.).
Syntaxe
Fonction Constructeur(param1: Type1, param2: Type2)
Soi.champ1 = param1
Soi.champ2 = param2
FinFonction
Exemple
Classe Personne
Variable nom: Chaine
Variable age: Entier
Fonction Constructeur(n: Chaine, a: Entier)
Soi.nom = n
Soi.age = a
FinFonction
Fonction SePresenter()
Ecrire("Je suis ", Soi.nom, ", j'ai ", Soi.age, " ans.\n")
FinFonction
FinClasse
Variable p: Personne
Debut
p = Nouveau Personne("Ada", 30)
p.SePresenter()
Fin
Ce programme affiche :
Je suis Ada, j'ai 30 ans.
3. Créer un objet avec Nouveau
Nouveau NomClasse(arguments) crée un nouvel objet et appelle son Constructeur avec les arguments fournis. Le résultat s'affecte à une variable typée avec le nom de la classe, exactement comme on écrirait Variable x: Entier pour un entier.
Variable p: Personne
Debut
p = Nouveau Personne("Ada", 30)
Fin
Quelques erreurs courantes que l'interpréteur détecte pour vous :
Nouveausur une classe qui n'existe pas → erreurla classe '...' n'est pas définie.- Un nombre d'arguments différent de celui attendu par
Constructeur→ erreur explicite indiquant le nombre attendu et le nombre fourni.
4. Soi : accéder à l'instance courante
À l'intérieur d'une méthode (ou du constructeur), Soi désigne l'objet sur lequel la méthode a été appelée — l'équivalent de self/this dans d'autres langages. Il permet de lire ou modifier les champs de l'objet, et d'appeler ses autres méthodes.
Fonction SePresenter()
Ecrire("Je suis ", Soi.nom, ", j'ai ", Soi.age, " ans.\n")
FinFonction
Soi n'a de sens qu'à l'intérieur d'une méthode : l'utiliser ailleurs (par exemple directement dans le bloc Debut ... Fin) provoque une erreur, puisque Soi n'y est pas déclaré.
5. Lire, écrire et appeler
Une fois un objet créé, on accède à ses champs et méthodes avec la notation pointée (.), aussi bien depuis l'extérieur de la classe qu'à travers Soi depuis l'intérieur :
p.nom = "Grace" // écriture d'un champ (la valeur est convertie au type déclaré) Ecrire(p.nom) // lecture d'un champ p.SePresenter() // appel d'une méthode
Piège à éviter : une variable objet déclarée mais jamais initialisée avec
Nouveaune contient rien d'utilisable. L'utiliser (par exemple lire un de ses champs) avant de lui avoir affectéNouveau NomClasse(...)provoque une erreur d'exécution explicite plutôt qu'un comportement silencieux.
6. Composition : un objet dans un autre objet
Un champ peut lui-même être typé avec le nom d'une autre classe. On parle alors de composition : un objet « contient » un autre objet. Les accès en chaîne (p.adresse.ville) fonctionnent naturellement.
Classe Adresse
Variable ville: Chaine
Fonction Constructeur(v: Chaine)
Soi.ville = v
FinFonction
FinClasse
Classe Personne
Variable nom: Chaine
Variable adresse: Adresse
Fonction Constructeur(n: Chaine, a: Adresse)
Soi.nom = n
Soi.adresse = a
FinFonction
Fonction Ville(): Chaine
Retourner Soi.adresse.ville
FinFonction
FinClasse
Variable a: Adresse
Variable p: Personne
Debut
a = Nouveau Adresse("Paris")
p = Nouveau Personne("Ada", a)
Ecrire(p.nom, " habite a ", p.Ville(), ".\n")
Fin
Ce programme affiche :
Ada habite a Paris.
7. Les objets sont des références
Une variable objet ne contient pas une copie de l'objet, mais une référence vers lui. Affecter une variable objet à une autre ne duplique donc pas l'objet : les deux variables désignent le même objet.
Classe Compteur
Variable n: Entier
FinClasse
Variable c1, c2: Compteur
Debut
c1 = Nouveau Compteur()
c2 = c1
c2.n = 42
Ecrire(c1.n)
Fin
Ce programme affiche 42, alors que c'est c2 qui a été modifié : c1 et c2 désignent le même objet. Pour la même raison, comparer deux objets avec == compare leur identité (s'agit-il du même objet ?) et non le contenu de leurs champs — contrairement aux Chaine, Entier ou Decimal, qui se comparent par valeur.
8. Classes et modules
Une classe peut être définie dans un module (un fichier .cfr séparé, voir la page Modules) au même titre qu'une fonction, et importée de la même manière.
Exemple – Module FormesGeo.cfr
Classe Cercle
Variable rayon: Decimal
Fonction Constructeur(r: Decimal)
Soi.rayon = r
FinFonction
Fonction Aire(): Decimal
Retourner 3.14159 * Soi.rayon * Soi.rayon
FinFonction
FinClasse
Import complet du module
Avec Importer, la classe s'utilise préfixée du nom du module, aussi bien dans le type que dans Nouveau :
Importer FormesGeo
Variable c: FormesGeo.Cercle
Debut
c = Nouveau FormesGeo.Cercle(2.0)
Ecrire(c.Aire())
Fin
Import ciblé de la classe
Avec Depuis ... Importer, la classe s'utilise sans préfixe :
Depuis FormesGeo Importer Cercle
Variable c: Cercle
Debut
c = Nouveau Cercle(1.0)
Ecrire(c.Aire())
Fin
Limite connue : si un module contient plusieurs classes qui se référencent entre elles par leur nom non préfixé (par exemple une classe
Roueutilisée comme type de champ dans une classeVoituredu même module), l'import échoue. Une classe seule, ou plusieurs classes indépendantes les unes des autres, s'importent en revanche sans problème.
9. Limites actuelles
Le support de la programmation orientée objet en CodeFR reste volontairement minimal :
- Pas d'héritage : une classe ne peut pas hériter d'une autre.
- Pas de modificateurs de visibilité : tous les champs et méthodes sont accessibles depuis n'importe où (pas de
public/privé). - Pas de surcharge de méthodes : une méthode ne peut pas avoir plusieurs versions selon les types de ses paramètres.
Résumé
| Élément | Exemple | Description |
|---|---|---|
| Déclaration de classe | Classe Personne ... FinClasse |
Regroupe champs et méthodes |
| Constructeur | Fonction Constructeur(n: Chaine) |
Initialise les champs à la création |
| Création d'un objet | p = Nouveau Personne("Ada", 30) |
Instancie la classe et appelle le constructeur |
| Référence à soi-même | Soi.nom |
Accède à l'instance courante dans une méthode |
| Lecture/écriture d'un champ | p.nom / p.nom = "Grace" |
Accède ou modifie un champ |
| Appel de méthode | p.SePresenter() |
Exécute une méthode de l'objet |
| Classe importée | Depuis FormesGeo Importer Cercle |
Utilise une classe définie dans un module |
La programmation orientée objet permet de regrouper données et comportements liés, et de modéliser des concepts du monde réel de façon claire — un outil précieux dès que vos programmes CodeFR grandissent en complexité.