Controllo di accesso (F#)
Il controllo di accesso si riferisce alla dichiarazione dei client che possono utilizzare determinati elementi di programma, ad esempio tipi, metodi e funzioni.
Nozioni di base del controllo di accesso
In F# gli identificatori del controllo di accesso public, internal e private possono essere applicati a moduli, tipi, metodi, definizioni di valori, funzioni, proprietà e campi espliciti.
public indica che l'accesso all'entità può essere eseguito da tutti i chiamanti.
internal indica che l'accesso all'entità può essere eseguito solo dallo stesso assembly.
private indica che l'accesso all'entità può essere eseguito solo dal modulo o dal tipo che la contiene.
[!NOTA]
L'identificatore di accesso protected non è utilizzato in F#, ma è accettabile se si utilizzano tipi creati in linguaggi che supportano l'accesso protected.Se pertanto si esegue l'override di un metodo protetto, il metodo rimane accessibile solo all'interno della classe e dei relativi discendenti.
In generale, l'identificatore viene posizionato davanti al nome dell'entità, ad eccezione di quando viene utilizzato un identificatore mutable o inline, che appare dopo l'identificatore del controllo di accesso.
Se non viene utilizzato alcun identificatore di accesso, l'impostazione predefinita è public, ad eccezione delle associazioni let in un tipo, che sono sempre impostate come private per il tipo.
Le firme in F# forniscono un altro meccanismo per il controllo di accesso agli elementi del programma F#.Le firme non sono obbligatorie per il controllo di accesso.Per ulteriori informazioni, vedere Firme (F#).
Regole per il controllo di accesso
Il controllo di accesso è soggetto alle regole seguenti:
Le dichiarazioni di ereditarietà (ovvero, l'utilizzo di inherit per specificare una classe di base per una classe), le dichiarazioni di interfaccia (ovvero, la specifica che una classe implementa un'interfaccia) e i membri astratti hanno sempre la stessa accessibilità del tipo che li contiene.Non è pertanto possibile utilizzare un identificatore del controllo di accesso in questi costrutti.
I singoli case di un'unione discriminata non possono avere modificatori del controllo di accesso propri, diversi dal tipo di unione.
I singoli campi di un tipo di record non possono disporre di propri modificatori del controllo di accesso separati dal tipo di record.
Esempio
Nel codice seguente viene illustrato l'utilizzo degli identificatori del controllo di accesso.Nel progetto sono presenti due file, Module1.fs e Module2.fs.Ogni file è implicitamente un modulo.Vi sono pertanto due moduli, Module1 e Module2.In Module1 sono definiti un tipo privato e un tipo interno.L'accesso al tipo privato non può essere eseguito da Module2, mentre al tipo interno sì.
// 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
Nel codice seguente viene testata l'accessibilità dei tipi creati in 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