Поделиться через


Свойства (F#)

Свойства — это члены, представляющие собой значения, связанные с объектом.

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

// Alternative syntax for a property that has get and set.
[ attributes-for-get ]
[ static ] member [accessibility-modifier-for-get] [self-identifier.]PropertyName =
      get-function-body
[ attributes-for-set ]
[ static ] member [accessibility-modifier-for-set] [self-identifier.]PropertyName
   with 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.
[ attributes ]
[ static ] member [accessibility-modifier] [self-identifier.]PropertyName
   with get() =
      get-function-body

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

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

Заметки

В объектно-ориентированном программировании свойства соответствуют отношению "имеет", представляя собой данные, связанные с экземплярами объекта или — в случае статических свойств — с типом.

Можно объявить свойства двумя способами в зависимости от того, требуется явно указать основное значение (также называемое резервного хранилища) для свойства или если требуется разрешить компилятору автоматически создавать хранилище данных.Как правило следует использовать более явным образом, если свойство имеет нетривиальный реализации и автоматическим способом свойство имеет достаточно простая обертка для значением или переменной.Чтобы явным образом объявить свойство с помощью member ключевое слово.За этим декларативным синтаксисом следует синтаксис, определяющий методы get и set, также называемые методами доступа.Различные формы явный синтаксис в разделе "синтаксис" используются для чтения и записи свойства только для чтения и записи.Для свойств, доступных только для чтения, определяется только метод get; для свойств, доступных только на запись, определяется только метод set.Обратите внимание, что, когда свойство имеет и метод доступа get, и метод доступа set, альтернативный синтаксис позволяет указать атрибуты и модификаторы доступности, разные для каждого из методов доступа, как показано в следующем коде.

// 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

В случае доступных для чтения и на запись свойств, имеющих и метод get, и метод set, методы get и set могут быть определены в обратном порядке.Другой вариант — вместо использования комбинированного синтаксиса можно записать синтаксис, показанный для случая "только метод get" и синтаксис, показанный для случая "только метод set".В этом случае будет проще закомментировать отдельно метод get или метод set, если это понадобится.Такая альтернатива использованию комбинированного синтаксиса показана в следующем коде.

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

Закрытые значения, в которых содержатся данные для свойств, называются резервными хранилищами.Чтобы компилятор автоматически создавать резервное хранилище, используйте ключевые слова member val, self-identifier опущен, а затем указать выражение для инициализации свойства.Если свойство является изменяемым, with get, set.Например следующий тип класса включает два автоматически реализуемые свойства. Property1доступно только для чтения и инициализируется значением аргумента конструктору первичного и Property2 — это свойство инициализируется пустой строкой:

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

Автоматически реализуемые свойства являются частью инициализации типа, поэтому они должны быть включены перед другими определения членов, так же, как let привязок и do привязки в определении типа.Обратите внимание, что выражение, которое инициализирует автоматически реализованного свойства вычисляется только при инициализации, а не каждый раз доступ к свойству.Это поведение отличается от поведения явно реализованные свойства.Что это фактически означает, что код для инициализации этих свойств будет добавлен в конструктор класса.Рассмотрим следующий код, это различие показано:

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.AutoProperty = %d" class1.AutoProperty
printfn "class1.ExplicitProperty = %d" class1.ExplicitProperty
printfn "class1.ExplicitProperty = %d" class1.ExplicitProperty

Output

  

Результат выполнения предыдущего кода показывает, что значение AutoProperty не изменяется при вызове многократно, тогда как ExplicitProperty изменяется каждый раз, когда он вызывается.Этот пример демонстрирует для автоматически реализованного свойства выражение не вычисляется каждый раз, как метод считывания свойства явно.

Предупреждающее замечаниеВнимание

Существуют некоторые библиотеки, например Entity Framework (System.Data.Entity), пользовательские операции в конструкторы базового класса, которые не могут работать с инициализации автоматически реализованных свойств.В этих случаях попробуйте использовать явные свойства.

Свойства могут быть членами классов, структур, размеченных объединений, записей, интерфейсов и расширений типов, а также могут определяться в выражениях объектов.

К свойствам можно применять атрибуты.Чтобы применить атрибут к свойству, запишите атрибут на отдельной строке перед свойством.Дополнительные сведения см. в разделе Атрибуты (F#).

По умолчанию свойства являются открытыми.К свойствам также можно применять модификаторы доступности.Чтобы применить модификатор доступности, добавьте его непосредственно перед именем свойства, если он должен применяться и к методу get, и к методу set; если уровни доступа для этих методов должны быть разными, добавляйте модификатор перед ключевыми словами get и set.Можно использовать следующий accessibility-modifier: public, private или internal.Дополнительные сведения см. в разделе Управление доступом (F#).

Реализации свойств выполняются при каждом обращении к свойству.

Статические свойства и свойства экземпляра

Свойства могут быть статическими или свойствами экземпляра.Статические свойства могут вызываться без экземпляра и используются для значений, связанных с типом, а не с отдельными объектами.Для статического свойства пропустите self-identifier.Self-identifier является обязательным для свойств экземпляра.

Следующее определение статического свойства основывается на сценарии, в котором имеется статическое поле myStaticValue, представляющее собой резервное хранилище для свойства.

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

Свойства также могут иметь вид массивов; в этом случае они называются индексированными свойствами.Дополнительные сведения см. в разделе Индексированные свойства (F#).

Аннотация типа для свойств

Во многих случаях компилятор располагает достаточной информацией для вывода типа свойства из типа резервного хранилища, однако можно задать тип явно, добавив аннотацию типа.

// 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

Использование методов доступа set свойств

Задавать свойства, предоставляющие методы доступа set, можно с помощью оператора <-.


// 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)

В результате получается 20.

Абстрактные свойства

Свойства могут быть абстрактными.Как и в случае с методами, термин абстрактный просто означает, что со свойством связана виртуальная ячейка отправки.Абстрактные свойства могут быть истинно абстрактными, т. е. не иметь определения в этом же классе.Содержащий такое свойство класс является, следовательно, абстрактным классом.Другой вариант — под абстрактностью может просто пониматься, что свойство является виртуальным; в этом случае определение должно присутствовать в этом же классе.Обратите внимание, что абстрактные свойства не должны быть закрытыми и, если один метод доступа является абстрактным, второй также должен быть абстрактным.Дополнительные сведения об абстрактных классах см. в разделе Абстрактные классы (F#).

// 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

См. также

Ссылки

Методы (F#)

Другие ресурсы

Члены (F#)