Compartir a través de


Propiedades (F#)

Las propiedades son miembros que representan valores asociados a un objeto .

Sintaxis

// Property that has both get and set defined.
[ attributes ]
[ static ] member [accessibility-modifier] [self-identifier.]PropertyName
with [ attributes-for-get ] [accessibility-modifier] get() =
    get-function-body
and [ attributes-for-set ] [accessibility-modifier] set parameter =
    set-function-body

// Alternative syntax for a property that has get and set.
[ static ] member [accessibility-modifier-for-get] [self-identifier.]PropertyName
with [ attributes-for-get ] get() =
    get-function-body
[ static ] member [accessibility-modifier-for-set] [self-identifier.]PropertyName
with [ attributes-for-set ] set parameter =
    set-function-body

// Property that has get only.
[ attributes ]
[ static ] member [accessibility-modifier] [self-identifier.]PropertyName =
    get-function-body

// Alternative syntax for property that has get only.
[ static ] member [accessibility-modifier] [self-identifier.]PropertyName
with [ attributes ] get() =
    get-function-body

// Property that has set only.
[ static ] member [accessibility-modifier] [self-identifier.]PropertyName
with [ attributes ] set parameter =
    set-function-body

// Automatically implemented properties.
[ attributes ]
[ static ] member val [accessibility-modifier] PropertyName = initialization-expression [ with get, set ]

Observaciones

Las propiedades representan la relación "tiene una" relación en la programación orientada a objetos, que representa los datos asociados a instancias de objeto o, para las propiedades estáticas, con el tipo .

Puede declarar propiedades de dos maneras, dependiendo de si desea especificar explícitamente el valor subyacente (también denominado almacén de respaldo) para la propiedad, o si desea permitir que el compilador genere automáticamente el almacén de respaldo. Por lo general, debe usar la forma más explícita si la propiedad tiene una implementación no trivial y la forma automática cuando la propiedad es simplemente un contenedor sencillo para un valor o variable. Para declarar una propiedad explícitamente, use la member palabra clave . Esta sintaxis declarativa va seguida de la sintaxis que especifica los get métodos y set , también descriptores de acceso con nombre. Las distintas formas de la sintaxis explícita que se muestra en la sección de sintaxis se usan para propiedades de solo lectura y escritura, de solo lectura y de solo escritura. En el caso de las propiedades de solo lectura, solo se define un get método; para las propiedades de solo escritura, solo se define un set método. Tenga en cuenta que cuando una propiedad tiene descriptores get de acceso y set , la sintaxis alternativa permite especificar atributos y modificadores de accesibilidad que son diferentes para cada descriptor de acceso, como se muestra en el código siguiente.

// A read-only property.
member this.MyReadOnlyProperty = myInternalValue
// A write-only property.
member this.MyWriteOnlyProperty with set (value) = myInternalValue <- value
// A read-write property.
member this.MyReadWriteProperty
    with get () = myInternalValue
    and set (value) = myInternalValue <- value

Para las propiedades de lectura y escritura, que tienen un get método y set , se puede invertir el orden de get y set . Como alternativa, puede proporcionar la sintaxis que se muestra solo para get y la sintaxis mostrada solo para set en lugar de usar la sintaxis combinada. Al hacerlo, resulta más fácil comentar el método o get individualset, si es algo que podría necesitar hacer. Esta alternativa al uso de la sintaxis combinada se muestra en el código siguiente.

member this.MyReadWriteProperty with get () = myInternalValue
member this.MyReadWriteProperty with set (value) = myInternalValue <- value

Los valores privados que contienen los datos de las propiedades se denominan almacenes de respaldo. Para que el compilador cree automáticamente el almacén de respaldo, use las palabras clave member val, omita el identificador propio y proporcione una expresión para inicializar la propiedad. Si la propiedad es mutable, incluya with get, set. Por ejemplo, el siguiente tipo de clase incluye dos propiedades implementadas automáticamente. Property1 es de solo lectura y se inicializa en el argumento proporcionado al constructor principal y Property2 es una propiedad settable inicializada en una cadena vacía:

type MyClass(property1 : int) =
    member val Property1 = property1
    member val Property2 = "" with get, set

Las propiedades implementadas automáticamente forman parte de la inicialización de un tipo, por lo que deben incluirse antes de cualquier otra definición de miembro, al igual let que los enlaces y do enlaces en una definición de tipo. Tenga en cuenta que la expresión que inicializa una propiedad implementada automáticamente solo se evalúa tras la inicialización y no cada vez que se accede a la propiedad. Este comportamiento contrasta con el comportamiento de una propiedad implementada explícitamente. Lo que esto significa eficazmente es que el código para inicializar estas propiedades se agrega al constructor de una clase. Tenga en cuenta el código siguiente que muestra esta diferencia:

type MyClass() =
    let random  = new System.Random()
    member val AutoProperty = random.Next() with get, set
    member this.ExplicitProperty = random.Next()

let class1 = new MyClass()

printfn $"class1.AutoProperty = %d{class1.AutoProperty}"
printfn $"class1.ExplicitProperty = %d{class1.ExplicitProperty}"

Salida

class1.AutoProperty = 1853799794
class1.AutoProperty = 1853799794
class1.ExplicitProperty = 978922705
class1.ExplicitProperty = 1131210765

La salida del código anterior muestra que el valor de AutoProperty no se modifica cuando se llama repetidamente, mientras que los ExplicitProperty cambios cada vez que se llama a . Esto demuestra que la expresión de una propiedad implementada automáticamente no se evalúa cada vez, como es el método getter para la propiedad explícita.

Advertencia

Hay algunas bibliotecas, como Entity Framework (System.Data.Entity) que realizan operaciones personalizadas en constructores de clase base que no funcionan bien con la inicialización de propiedades implementadas automáticamente. En esos casos, intente usar propiedades explícitas.

Las propiedades pueden ser miembros de clases, estructuras, uniones discriminadas, registros, interfaces y extensiones de tipo, y también se pueden definir en expresiones de objeto.

Los atributos se pueden aplicar a las propiedades. Para aplicar un atributo a una propiedad, escriba el atributo en una línea independiente antes de la propiedad . Para obtener más información, vea atributos de .

De forma predeterminada, las propiedades son públicas. Los modificadores de accesibilidad también se pueden aplicar a las propiedades. Para aplicar un modificador de accesibilidad, agréguelo inmediatamente antes del nombre de la propiedad si está pensado para aplicarse a los get métodos y set ; agréguelo antes de las get palabras clave y set si se requiere una accesibilidad diferente para cada descriptor de acceso. El modificador de accesibilidad puede ser uno de los siguientes: public, private, internal. Para obtener más información, consulte Control de acceso.

Las implementaciones de propiedades se ejecutan cada vez que se accede a una propiedad.

Propiedades estáticas e de instancia

Las propiedades pueden ser propiedades estáticas o de instancia. Las propiedades estáticas se pueden invocar sin una instancia y se usan para los valores asociados al tipo, no con objetos individuales. En el caso de las propiedades estáticas, omita el identificador propio. El identificador propio es necesario para las propiedades de instancia.

La siguiente definición de propiedad estática se basa en un escenario en el que se tiene un campo myStaticValue estático que es el almacén de respaldo de la propiedad .

static member MyStaticProperty
    with get() = myStaticValue
    and set(value) = myStaticValue <- value

Las propiedades también pueden ser similares a matrices, en cuyo caso se denominan propiedades indexadas. Para obtener más información, vea Propiedades indexadas.

Anotación de tipo para propiedades

En muchos casos, el compilador tiene suficiente información para deducir el tipo de una propiedad del tipo del almacén de respaldo, pero puede establecer el tipo explícitamente agregando una anotación de tipo.

// To apply a type annotation to a property that does not have an explicit
// get or set, apply the type annotation directly to the property.
member this.MyProperty1 : int = myInternalValue
// If there is a get or set, apply the type annotation to the get or set method.
member this.MyProperty2 with get() : int = myInternalValue

Usar descriptores de acceso de conjunto de propiedades

Puede establecer propiedades que proporcionen set descriptores de acceso mediante el <- operador .

// Assume that the constructor argument sets the initial value of the
// internal backing store.
let mutable myObject = new MyType(10)
myObject.MyProperty <- 20
printfn "%d" (myObject.MyProperty)

La salida es 20.

Propiedades abstractas

Las propiedades pueden ser abstractas. Al igual que con los métodos, abstract simplemente significa que hay un envío virtual asociado a la propiedad . Las propiedades abstractas pueden ser realmente abstractas, es decir, sin una definición en la misma clase. Por lo tanto, la clase que contiene dicha propiedad es una clase abstracta. Como alternativa, abstract puede significar simplemente que una propiedad es virtual y, en ese caso, una definición debe estar presente en la misma clase. Tenga en cuenta que las propiedades abstractas no deben ser privadas y, si un descriptor de acceso es abstracto, el otro también debe ser abstracto. Para obtener más información sobre las clases abstractas, vea Clases abstractas.

// Abstract property in abstract class.
// The property is an int type that has a get and
// set method
[<AbstractClass>]
type AbstractBase() =
    abstract Property1: int with get, set

// Implementation of the abstract property
type Derived1() =
    inherit AbstractBase()
    let mutable value = 10

    override this.Property1
        with get () = value
        and set (v: int) = value <- v

// A type with a "virtual" property.
type Base1() =
    let mutable value = 10
    abstract Property1: int with get, set

    default this.Property1
        with get () = value
        and set (v: int) = value <- v

// A derived type that overrides the virtual property
type Derived2() =
    inherit Base1()
    let mutable value2 = 11

    override this.Property1
        with get () = value2
        and set (v) = value2 <- v

Consulte también