Control de acceso (F#)
El control de acceso se refiere a declarar qué clientes pueden utilizar determinados elementos de programa, tales como tipos, métodos y funciones.
Fundamentos del control de acceso
En F#, los especificadores de control de acceso public, internal y private se pueden aplicar a los módulos, tipos, métodos, definiciones de valor, funciones, propiedades y campos explícitos.
public indica que todos los llamadores pueden tener acceso a la entidad.
internal indica que se puede tener acceso a la entidad únicamente desde el mismo ensamblado.
private indica que se puede tener acceso a la entidad únicamente desde el módulo o el tipo envolvente.
Nota
El especificador de acceso protected no se utiliza en F#, si bien es aceptable si se utilizan tipos creados en lenguajes que admiten el acceso protected. Así pues, si se reemplaza un método protegido, el método permanecerá accesible únicamente dentro de la clase y de sus descendientes.
En general, el especificador se coloca delante del nombre de la entidad, excepto cuando se utiliza un especificador mutable o inline, que aparecen después del especificador de control de acceso.
Si no se utiliza ningún especificador de acceso, el valor predeterminado es public, salvo para los enlaces let de un tipo, que siempre son private para el tipo.
Las signaturas de F# proporcionan otro mecanismo para controlar el acceso a los elementos de programa de F#. No se requieren signaturas para el control de acceso. Para obtener más información, vea Signaturas (F#).
Reglas de control de acceso
El control de acceso está sujeto a las reglas siguientes:
Las declaraciones de herencia (es decir, el uso de inherit para especificar una clase base para una clase), las declaraciones de interfaz (es decir, especificar que una clase implementa una interfaz) y los miembros abstractos siempre tienen la misma accesibilidad que el tipo envolvente. Por consiguiente, un especificador de control de acceso no se puede utilizar en estas construcciones.
Los casos individuales de una unión discriminada no pueden tener sus propios modificadores de control de acceso independientes del tipo de unión.
Los campos individuales de un tipo de registro no pueden tener sus propios modificadores de control de acceso independientes del tipo de registro.
Ejemplo
En el código siguiente se muestra el uso de especificadores de control de acceso. Hay dos objetos archivos en el proyecto, Module1.fs y Module2.fs. Cada archivo es, implícitamente, un módulo. Por lo tanto, hay dos módulos, Module1 y Module2. En Module1 se definen un tipo privado y un tipo interno. No se puede tener acceso al tipo privado desde Module2, pero sí al interno.
// 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
En el código siguiente se prueba la accesibilidad de los tipos creados en 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