Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Cet article explique comment définir et utiliser des constructeurs pour créer et initialiser des objets de classe et de structure.
Construction d’objets de classe
Les objets des types de classes ont des constructeurs. Il existe deux types de constructeurs. Il s’agit du constructeur principal, dont les paramètres apparaissent entre parenthèses juste après le nom du type. Si vous le souhaitez, vous pouvez spécifier des constructeurs supplémentaires à l’aide du new mot clé. Tous ces constructeurs supplémentaires doivent appeler le constructeur principal.
Le constructeur principal contient let et do lie des liaisons qui apparaissent au début de la définition de classe. Une let liaison déclare des champs privés et des méthodes de la classe ; une do liaison exécute du code. Pour plus d’informations sur let les liaisons dans les constructeurs de classes, consultez let Bindings in Classes. Pour plus d’informations sur do les liaisons dans les constructeurs, consultez do Liaisons dans les classes.
Quel que soit le constructeur que vous souhaitez appeler est un constructeur principal ou un constructeur supplémentaire, vous pouvez créer des objets à l’aide d’une new expression, avec ou sans le mot clé facultatif new . Vous initialisez vos objets avec des arguments de constructeur, soit en listant les arguments dans l’ordre et séparés par des virgules et placés entre parenthèses, soit en utilisant des arguments nommés et des valeurs entre parenthèses. Vous pouvez également définir des propriétés sur un objet pendant la construction de l’objet à l’aide des noms de propriétés et attribuer des valeurs tout comme vous utilisez des arguments de constructeur nommés.
Le code suivant illustre une classe qui a un constructeur et différentes façons de créer des objets :
// This class has a primary constructor that takes three arguments
// and an additional constructor that calls the primary constructor.
type MyClass(x0, y0, z0) =
let mutable x = x0
let mutable y = y0
let mutable z = z0
do
printfn "Initialized object that has coordinates (%d, %d, %d)" x y z
member this.X with get() = x and set(value) = x <- value
member this.Y with get() = y and set(value) = y <- value
member this.Z with get() = z and set(value) = z <- value
new() = MyClass(0, 0, 0)
// Create by using the new keyword.
let myObject1 = new MyClass(1, 2, 3)
// Create without using the new keyword.
let myObject2 = MyClass(4, 5, 6)
// Create by using named arguments.
let myObject3 = MyClass(x0 = 7, y0 = 8, z0 = 9)
// Create by using the additional constructor.
let myObject4 = MyClass()
La sortie est la suivante :
Initialized object that has coordinates (1, 2, 3)
Initialized object that has coordinates (4, 5, 6)
Initialized object that has coordinates (7, 8, 9)
Initialized object that has coordinates (0, 0, 0)
Construction de structures
Les structures suivent toutes les règles des classes. Par conséquent, vous pouvez avoir un constructeur principal et vous pouvez fournir des constructeurs supplémentaires à l’aide newde . Toutefois, il existe une différence importante entre les structures et les classes : les structures peuvent avoir un constructeur sans paramètre (autrement dit, un avec aucun argument), même si aucun constructeur principal n’est défini. Le constructeur sans paramètre initialise tous les champs à la valeur par défaut de ce type, généralement zéro ou son équivalent. Les constructeurs que vous définissez pour les structures doivent avoir au moins un argument afin qu’ils ne soient pas en conflit avec le constructeur sans paramètre.
En outre, les structures ont souvent des champs créés à l’aide du val mot clé ; les classes peuvent également avoir ces champs. Les structures et classes qui ont des champs définis à l’aide du val mot clé peuvent également être initialisées dans des constructeurs supplémentaires à l’aide d’expressions d’enregistrement, comme indiqué dans le code suivant.
type MyStruct =
struct
val X : int
val Y : int
val Z : int
new(x, y, z) = { X = x; Y = y; Z = z }
end
let myStructure1 = new MyStruct(1, 2, 3)
Pour plus d’informations, consultez Champs explicites : le val mot clé.
Exécution d’effets secondaires dans les constructeurs
Un constructeur principal dans une classe peut exécuter du code dans une do liaison. Toutefois, que se passe-t-il si vous devez exécuter du code dans un constructeur supplémentaire, sans do liaison ? Pour ce faire, vous utilisez le then mot clé.
// Executing side effects in the primary constructor and
// additional constructors.
type Person(nameIn : string, idIn : int) =
let mutable name = nameIn
let mutable id = idIn
do printfn "Created a person object."
member this.Name with get() = name and set(v) = name <- v
member this.ID with get() = id and set(v) = id <- v
new() =
Person("Invalid Name", -1)
then
printfn "Created an invalid person object."
let person1 = new Person("Humberto Acevedo", 123458734)
let person2 = new Person()
Les effets secondaires du constructeur principal s’exécutent toujours. Par conséquent, la sortie est la suivante :
Created a person object.
Created a person object.
Created an invalid person object.
La raison pour laquelle then est nécessaire au lieu d’une autre do est que le do mot clé a sa signification standard de limiter une unitexpression -retournant lorsqu’elle est présente dans le corps d’un constructeur supplémentaire. Elle n’a qu’une signification particulière dans le contexte des constructeurs principaux.
Identificateurs d’auto-identificateurs dans les constructeurs
Dans d’autres membres, vous fournissez un nom pour l’objet actif dans la définition de chaque membre. Vous pouvez également placer l’identificateur automatique sur la première ligne de la définition de classe à l’aide du as mot clé immédiatement après les paramètres du constructeur. L’exemple suivant illustre cette syntaxe.
type MyClass1(x) as this =
// This use of the self identifier produces a warning - avoid.
let x1 = this.X
// This use of the self identifier is acceptable.
do printfn "Initializing object with X =%d" this.X
member this.X = x
Dans d’autres constructeurs, vous pouvez également définir un auto-identificateur en plaçant la as clause juste après les paramètres du constructeur. L’exemple suivant illustre cette syntaxe :
type MyClass2(x : int) =
member this.X = x
new() as this = MyClass2(0) then printfn "Initializing with X = %d" this.X
Des problèmes peuvent se produire lorsque vous essayez d’utiliser un objet avant qu’il soit entièrement défini. Par conséquent, les utilisations de l’identificateur automatique peuvent entraîner l’émission d’un avertissement et l’insertion de vérifications supplémentaires pour s’assurer que les membres d’un objet ne sont pas accessibles avant l’initialisation de l’objet. Vous devez uniquement utiliser l’identificateur automatique dans les do liaisons du constructeur principal, ou après le then mot clé dans des constructeurs supplémentaires.
Le nom de l’identificateur automatique n’a pas besoin d’être this. Il peut s’agir de n’importe quel identificateur valide.
Affectation de valeurs à des propriétés lors de l’initialisation
Vous pouvez affecter des valeurs aux propriétés d’un objet de classe dans le code d’initialisation en ajoutant une liste d’affectations du formulaire property = value à la liste d’arguments d’un constructeur. Ceci est illustré dans l’exemple de code suivant :
type Account() =
let mutable balance = 0.0
let mutable number = 0
let mutable firstName = ""
let mutable lastName = ""
member this.AccountNumber
with get() = number
and set(value) = number <- value
member this.FirstName
with get() = firstName
and set(value) = firstName <- value
member this.LastName
with get() = lastName
and set(value) = lastName <- value
member this.Balance
with get() = balance
and set(value) = balance <- value
member this.Deposit(amount: float) = this.Balance <- this.Balance + amount
member this.Withdraw(amount: float) = this.Balance <- this.Balance - amount
let account1 = new Account(AccountNumber=8782108,
FirstName="Darren", LastName="Parker",
Balance=1543.33)
La version suivante du code précédent illustre la combinaison d’arguments ordinaires, d’arguments facultatifs et de paramètres de propriété dans un appel de constructeur :
type Account(accountNumber : int, ?first: string, ?last: string, ?bal : float) =
let mutable balance = defaultArg bal 0.0
let mutable number = accountNumber
let mutable firstName = defaultArg first ""
let mutable lastName = defaultArg last ""
member this.AccountNumber
with get() = number
and set(value) = number <- value
member this.FirstName
with get() = firstName
and set(value) = firstName <- value
member this.LastName
with get() = lastName
and set(value) = lastName <- value
member this.Balance
with get() = balance
and set(value) = balance <- value
member this.Deposit(amount: float) = this.Balance <- this.Balance + amount
member this.Withdraw(amount: float) = this.Balance <- this.Balance - amount
let account1 = new Account(8782108, bal = 543.33,
FirstName="Raman", LastName="Iyer")
Constructeurs dans la classe héritée
Lorsque vous héritez d’une classe de base qui a un constructeur, vous devez spécifier ses arguments dans la clause hérite. Pour plus d’informations, consultez Constructeurs et héritage.
Constructeurs statiques ou constructeurs de type
En plus de spécifier du code pour créer des objets, des liaisons et do des statiques let peuvent être créés dans des types de classes qui s’exécutent avant que le type ne soit utilisé pour effectuer l’initialisation au niveau du type. Pour plus d’informations, consultez let Liaisons dans les classes et do les liaisons dans les classes.