Contrôle d’accès
Le contrôle d’accès consiste à déclarer les clients qui peuvent utiliser certains éléments de programme, tels que des types, des méthodes et des fonctions.
Notions de base du contrôle d’accès
En F#, les spécificateurs de contrôle d’accès public
, internal
et private
peuvent être appliqués aux modules, types, méthodes, définitions de valeurs, fonctions, propriétés et champs explicites.
public
indique que l’entité est accessible à tous les appelants.internal
indique que l’entité n’est accessible qu’à partir du même assembly.private
indique que l’entité n’est accessible qu’à partir du type ou du module englobant.
Notes
Le spécificateur d’accès protected
n’est pas utilisé en F#, bien qu’il soit acceptable si vous utilisez des types créés dans des langages qui prennent en charge l’accès protected
. Par conséquent, si vous substituez une méthode protégée, votre méthode reste accessible uniquement dans la classe et ses descendants.
Le spécificateur d’accès est placé devant le nom de l’entité.
Si aucun spécificateur d’accès n’est utilisé, la valeur par défaut est public
, sauf pour les liaisons let
dans un type qui sont toujours private
pour le type.
Les signatures en F# fournissent un autre mécanisme pour contrôler l’accès aux éléments de programme F#. Les signatures ne sont pas exigées pour le contrôle d’accès. Pour plus d’informations, consultez Signatures.
Règles de contrôle d’accès
Le contrôle d’accès est soumis aux règles suivantes :
Les déclarations d’héritage (c’est-à-dire l’utilisation de
inherit
pour spécifier une classe de base pour une classe), les déclarations d’interface (c’est-à-dire la spécification d’une classe pour implémenter une interface) et les membres abstraits ont toujours la même accessibilité que le type englobant. Un spécificateur de contrôle d’accès ne peut donc pas être utilisé sur ces constructions.L’accessibilité pour des cas individuels dans une union discriminée est déterminée par l’accessibilité de l’union discriminée elle-même. Autrement dit, un cas d’union particulier n’est pas moins accessible que l’union elle-même.
L’accessibilité pour les champs individuels d’un type d’enregistrement est déterminée par l’accessibilité de l’enregistrement lui-même. Autrement dit, une étiquette d’enregistrement particulière n’est pas moins accessible que l’enregistrement lui-même.
Exemple
Le code suivant illustre l’utilisation des spécificateurs de contrôle d’accès. Le projet comprend deux fichiers : Module1.fs
et Module2.fs
. Chaque fichier est implicitement un module. Il y a donc deux modules : Module1
et Module2
. Un type privé et un type interne sont définis dans Module1
. Le type privé n’est pas accessible à partir de Module2
, contrairement au type interne.
// Module1.fs
module Module1
// This type is not usable outside of this file
type private MyPrivateType() =
// x is private since this is an internal let binding
let x = 5
// X is private and does not appear in the QuickInfo window
// when viewing this type in the Visual Studio editor
member private this.X() = 10
member this.Z() = x * 100
type internal MyInternalType() =
let x = 5
member private this.X() = 10
member this.Z() = x * 100
// Top-level let bindings are public by default,
// so "private" and "internal" are needed here since a
// value cannot be more accessible than its type.
let private myPrivateObj = new MyPrivateType()
let internal myInternalObj = new MyInternalType()
// let bindings at the top level are public by default,
// so result1 and result2 are public.
let result1 = myPrivateObj.Z
let result2 = myInternalObj.Z
Le code suivant teste l’accessibilité des types créés dans Module1.fs
.
// Module2.fs
module Module2
open Module1
// The following line is an error because private means
// that it cannot be accessed from another file or module
// let private myPrivateObj = new MyPrivateType()
let internal myInternalObj = new MyInternalType()
let result = myInternalObj.Z