Classe, structure

Classe

Classe en F♯ ≡ classe en C♯

  • Brique de base pour l'orienté-objet

  • Constructeur d'objets contenant des données de type défini et des méthodes

Définition d'une classe

  • Commence par type (comme tout type en F♯)

  • Nom de la classe généralement suivi du constructeur primaire

type CustomerName(firstName: string, lastName: string) =
    // Corps du constructeur primaire
    // Membres...

☝ Paramètres firstName et lastName visibles dans tout le corps de la classe

Classe générique

Paramètres génériques à spécifier car non inférés

type Tuple2_KO(item1, item2) = // ⚠️ 'item1' et 'item2': type 'obj' !
    // ...

type Tuple2<'T1, 'T2>(item1: 'T1, item2: 'T2) =  // 👌
    // ...

Constructeur secondaire

Syntaxe pour définir un autre constructeur : new(argument-list) = constructor-body

☝ Doit appeler le constructeur primaire !

☝ Paramètres des constructeurs : que en tuple, pas curryfiés !

Instanciation

Appel d'un des constructeurs, avec arguments en tuple

  • Ne pas oublier () si aucun argument, sinon on obtient une fonction !

Dans un let binding : new optionnel et non recommandé

  • let v = Vector(1.0, 2.0) 👌

  • let v = new Vector(1.0, 2.0)

Dans un use binding : new obligatoire

  • use d = new Disposable()

Initialisation des propriétés

On peut initialiser des propriétés avec setter à l'instanciation

  • Les spécifier en tant que arguments nommés dans l'appel au constructeur

  • Les placer après les éventuels arguments du constructeur :

💡 Équivalent de la syntaxe C♯ new PersonName("John") { Last = "Paul" }

Classe vide

Pour définir une classe sans corps, on utilise la syntaxe verbeuse class end :

Singleton

On peut définir une classe Singleton en rendant privé le constructeur primaire :

⚠️ Pas thread safe !

💡 On peut utiliser simplement une single-case union :

Classe abstraite

Annotée avec [<AbstractClass>]

Un des membres est abstrait :

  1. Déclaré avec mot clé abstract

  2. Pas d'implémentation par défaut avec mot clé default (Sinon le membre est virtuel)

Héritage via mot clé inherit, suivi de l'appel au constructeur de la classe de base

Exemple :

Champs

Convention de nommage : camelCase

2 types de champs : implicite ou explicite

  • Implicite ≃ Variable à l'intérieur du constructeur primaire

  • Explicite ≡ Champ classique d'une classe en C♯ / Java

Champ implicite

Syntaxe :

  • Variable : [static] let [ mutable ] variable-name = expression

  • Fonction : [static] let [ rec ] function-name function-args = expression

Notes

  • Déclaré avant les membres de la classe

  • Valeur initiale obligatoire

  • Privé

  • S'utilise sans devoir préfixer par le self-identifier

D'instance

Statique

Champ explicite

Déclaration du type, sans valeur initiale : val [ mutable ] [ access-modifier ] field-name : type-name

  • val mutable a: int → champ publique

  • val a: int → champ interne a@ + propriété a => a@

Champ vs propriété

Champ explicite ou implicite ou propriété

Champ explicite peu utilisé :

  • Ne concerne que les classes et structures

  • Utile avec fonction native manipulant la mémoire directement (Car ordre des champs préservés - cf. SharpLab)

  • Besoin d'une variable [<ThreadStatic>]

  • Interaction avec classe F♯ de code généré sans constructeur primaire

Champ implicite - let binding

  • Variable intermédiaire lors de la construction

Autres cas d'usages → propriété auto-implémentée

  • Exposer une valeur → member val

  • Exposer un "champ" mutable → member val ... with get, set

Structures

Alternatives aux classes mais + limités / héritage et récursivité

Même syntaxe que pour les classes mais avec en plus :

  • Soit attribut [<Struct>]

  • Soit bloc struct...end (fréquent)

Mis à jour

Ce contenu vous a-t-il été utile ?