Note
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de changer d’annuaire.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de changer d’annuaire.
Les classes sont des types qui représentent des objets qui peuvent avoir des propriétés, des méthodes et des événements.
Syntaxe
// Class definition:
type [access-modifier] type-name [type-params] [access-modifier] ( parameter-list ) [ as identifier ] =
[ class ]
[ inherit base-type-name(base-constructor-args) ]
[ let-bindings ]
[ do-bindings ]
member-list
...
[ end ]
// Mutually recursive class definitions:
type [access-modifier] type-name1 ...
and [access-modifier] type-name2 ...
...
Remarques
Les classes représentent la description fondamentale des types d’objets .NET ; la classe est le concept de type principal qui prend en charge la programmation orientée objet en F#.
Dans la syntaxe précédente, il type-name s’agit d’un identificateur valide. Décrit les type-params paramètres de type générique facultatifs. Il se compose de noms de paramètres de type et de contraintes entre crochets< (et >). Pour plus d’informations, consultez Génériques et contraintes. Les parameter-list paramètres du constructeur sont décrits. Le premier modificateur d’accès se rapporte au type ; le deuxième concerne le constructeur principal. Dans les deux cas, la valeur par défaut est public.
Vous spécifiez la classe de base d’une classe à l’aide du inherit mot clé. Vous devez fournir des arguments, entre parenthèses, pour le constructeur de classe de base.
Vous déclarez des champs ou des valeurs de fonction locaux à la classe à l’aide let de liaisons, et vous devez suivre les règles générales pour let les liaisons. La section inclut le do-bindings code à exécuter lors de la construction d’objets.
Il member-list comprend des constructeurs supplémentaires, des déclarations de méthode statique et d’instance, des déclarations d’interface, des liaisons abstraites et des déclarations de propriété et d’événement. Celles-ci sont décrites dans Membres.
Utilisé identifier avec le mot clé facultatif as donne un nom à la variable d’instance ou à l’identificateur auto, qui peut être utilisé dans la définition de type pour faire référence à l’instance du type. Pour plus d’informations, consultez la section Auto Identifiers plus loin dans cette rubrique.
Les mots clés class et end qui marquent le début et la fin de la définition sont facultatifs.
Les types récursifs mutuellement, qui sont des types qui font référence les uns aux autres, sont joints avec le and mot clé, tout comme les fonctions récursives mutuellement. Pour obtenir un exemple, consultez la section Types récursifs mutuellement.
Constructeurs
Le constructeur est du code qui crée une instance du type de classe. Les constructeurs pour les classes fonctionnent un peu différemment dans F# que dans d’autres langages .NET. Dans une classe F#, il existe toujours un constructeur principal dont les arguments sont décrits dans le parameter-list nom du type et dont le corps se compose des let liaisons (et let rec) au début de la déclaration de classe et des do liaisons qui suivent. Les arguments du constructeur principal sont dans l’étendue dans toute la déclaration de classe.
Vous pouvez ajouter des constructeurs supplémentaires à l’aide du new mot clé pour ajouter un membre, comme suit :
new(argument-list) = constructor-body
Le corps du nouveau constructeur doit appeler le constructeur principal spécifié en haut de la déclaration de classe.
L’exemple suivant illustre ce concept. Dans le code suivant, MyClass possède deux constructeurs, un constructeur principal qui accepte deux arguments et un autre constructeur qui ne prend aucun argument.
type MyClass1(x: int, y: int) =
do printfn "%d %d" x y
new() = MyClass1(0, 0)
let and do Bindings
Les let liaisons et do les liaisons d’une définition de classe forment le corps du constructeur de classe primaire, et par conséquent, ils s’exécutent chaque fois qu’une instance de classe est créée. Si une let liaison est une fonction, elle est compilée dans un membre. Si la let liaison est une valeur qui n’est pas utilisée dans une fonction ou un membre, elle est compilée dans une variable locale au constructeur. Sinon, elle est compilée dans un champ de la classe. Les do expressions suivantes sont compilées dans le constructeur principal et exécutent le code d’initialisation pour chaque instance. Étant donné que tous les constructeurs supplémentaires appellent toujours le constructeur principal, les let liaisons et do les liaisons s’exécutent toujours, quel que soit le constructeur appelé.
Les champs créés par let des liaisons sont accessibles dans toutes les méthodes et propriétés de la classe. Toutefois, ils ne peuvent pas être accessibles à partir de méthodes statiques, même si les méthodes statiques prennent une variable d’instance comme paramètre. Ils ne peuvent pas être accessibles à l’aide de l’identificateur automatique, s’il en existe un.
Identificateurs d’auto-identificateurs
Un auto-identificateur est un nom qui représente l’instance actuelle. Les identificateurs autonomes ressemblent au this mot clé en C# ou C++ ou Me en Visual Basic. Vous pouvez définir un auto-identificateur de deux façons différentes, selon que vous souhaitez que l’identificateur automatique soit dans l’étendue de la définition de classe entière ou simplement pour une méthode individuelle.
Pour définir un auto-identificateur pour la classe entière, utilisez le as mot clé après les parenthèses fermante de la liste des paramètres du constructeur et spécifiez le nom de l’identificateur.
Pour définir un auto-identificateur pour une seule méthode, fournissez l’identificateur automatique dans la déclaration de membre, juste avant le nom de la méthode et un point (.) comme séparateur.
L’exemple de code suivant illustre les deux façons de créer un auto-identificateur. Dans la première ligne, le as mot clé est utilisé pour définir l’identificateur automatique. Dans la cinquième ligne, l’identificateur this est utilisé pour définir un auto-identificateur dont l’étendue est limitée à la méthode PrintMessage.
type MyClass2(dataIn) as self =
let data = dataIn
do
self.PrintMessage()
member this.PrintMessage() =
printf "Creating MyClass2 with Data %d" data
Contrairement aux autres langages .NET, vous pouvez nommer l’identificateur automatique, mais vous le souhaitez ; vous n’êtes pas limité aux noms tels que self, Meou this.
L’identificateur automatique déclaré avec le as mot clé n’est initialisé qu’après le constructeur de base. Par conséquent, lorsqu’il est utilisé avant ou à l’intérieur du constructeur de base, System.InvalidOperationException: The initialization of an object or value resulted in an object or value being accessed recursively before it was fully initialized. est déclenché pendant l’exécution. Vous pouvez utiliser librement l’identificateur automatique après le constructeur de base, par exemple dans let les liaisons ou do les liaisons.
Paramètres de type générique
Les paramètres de type générique sont spécifiés entre crochets< (et >), sous la forme d’un guillemet unique suivi d’un identificateur. Plusieurs paramètres de type générique sont séparés par des virgules. Le paramètre de type générique est dans l’étendue dans toute la déclaration. L’exemple de code suivant montre comment spécifier des paramètres de type générique.
type MyGenericClass<'a>(x: 'a) =
do printfn "%A" x
Les arguments de type sont déduits lorsque le type est utilisé. Dans le code suivant, le type déduit est une séquence de tuples.
let g1 = MyGenericClass(seq { for i in 1..10 -> (i, i * i) })
Spécification de l’héritage
La inherit clause identifie la classe de base directe, s’il en existe un. Dans F#, une seule classe de base directe est autorisée. Les interfaces qu’une classe implémente ne sont pas considérées comme des classes de base. Les interfaces sont abordées dans la rubrique Interfaces .
Vous pouvez accéder aux méthodes et propriétés de la classe de base à partir de la classe dérivée à l’aide du mot clé base de langage en tant qu’identificateur, suivi d’un point (.) et du nom du membre.
Pour plus d’informations, consultez Héritage.
Section Membres
Vous pouvez définir des méthodes statiques ou d’instance, des propriétés, des implémentations d’interface, des membres abstraits, des déclarations d’événements et des constructeurs supplémentaires dans cette section. Laissez et effectuez des liaisons ne peuvent pas apparaître dans cette section. Étant donné que les membres peuvent être ajoutés à une variété de types F# en plus des classes, ils sont abordés dans une rubrique distincte, Membres.
Types récursifs mutuellement
Lorsque vous définissez des types qui font référence les uns aux autres de manière circulaire, vous chaînez ensemble les définitions de type à l’aide du and mot clé. Le and mot clé remplace le type mot clé sur tous, à l’exception de la première définition, comme suit.
open System.IO
type Folder(pathIn: string) =
let path = pathIn
let filenameArray: string array = Directory.GetFiles(path)
member this.FileArray = Array.map (fun elem -> new File(elem, this)) filenameArray
and File(filename: string, containingFolder: Folder) =
member this.Name = filename
member this.ContainingFolder = containingFolder
let folder1 = new Folder(".")
for file in folder1.FileArray do
printfn "%s" file.Name
La sortie est une liste de tous les fichiers du répertoire actif.
Quand utiliser des classes, des unions, des enregistrements et des structures
Étant donné la variété de types à choisir, vous devez avoir une bonne compréhension de ce que chaque type est conçu pour sélectionner le type approprié pour une situation particulière. Les classes sont conçues pour une utilisation dans les contextes de programmation orienté objet. La programmation orientée objet est le paradigme dominant utilisé dans les applications écrites pour le .NET Framework. Si votre code F# doit travailler en étroite collaboration avec .NET Framework ou une autre bibliothèque orientée objet, et surtout si vous devez étendre à partir d’un système de type orienté objet tel qu’une bibliothèque d’interface utilisateur, les classes sont probablement appropriées.
Si vous n’interopérez pas étroitement avec du code orienté objet, ou si vous écrivez du code autonome et donc protégé contre une interaction fréquente avec du code orienté objet, vous devez envisager d’utiliser un mélange de classes, d’enregistrements et d’unions discriminatoires. Une union unique et bien pensée, avec un code de correspondance de modèle approprié, peut souvent être utilisée comme alternative plus simple à une hiérarchie d’objets. Pour plus d’informations sur les syndicats discriminatoires, consultez Les syndicats discriminatoires.
Les enregistrements ont l’avantage d’être plus simples que les classes, mais les enregistrements ne sont pas appropriés lorsque les demandes d’un type dépassent ce qui peut être accompli avec leur simplicité. Les enregistrements sont essentiellement des agrégats simples de valeurs, sans constructeurs distincts qui peuvent effectuer des actions personnalisées, sans champs masqués et sans implémentations d’héritage ou d’interface. Bien que les membres tels que les propriétés et les méthodes puissent être ajoutés aux enregistrements pour rendre leur comportement plus complexe, les champs stockés dans un enregistrement sont toujours un agrégat simple de valeurs. Pour plus d’informations sur les enregistrements, consultez Enregistrements.
Les structures sont également utiles pour les petits agrégats de données, mais elles diffèrent des classes et des enregistrements dans le cas où elles sont des types de valeurs .NET. Les classes et enregistrements sont des types de référence .NET. La sémantique des types valeur et des types de référence est différente dans cette valeur. Cela signifie qu’ils sont copiés bits pour bit lorsqu’ils sont passés en tant que paramètre ou retournés à partir d’une fonction. Ils sont également stockés sur la pile ou, s’ils sont utilisés comme champ, incorporés à l’intérieur de l’objet parent au lieu d’être stockés dans leur propre emplacement distinct sur le tas. Par conséquent, les structures sont appropriées pour les données fréquemment sollicitées lorsque la surcharge liée à l’accès au tas est un problème. Pour plus d’informations sur les structures, consultez Structs.