プロパティ (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 ]
解説
プロパティは、オブジェクト指向プログラミングにおける "has a" 関係を表し、オブジェクト インスタンスまたは型 (静的プロパティの場合) に関連付けられるデータを表します。
プロパティは、基になる値 ("バッキング ストア"とも呼ばれます) を明示的に指定するかどうかや、用のバッキング ストアを自動的に生成するコンパイラを許可するかどうかによっては、2 つの方法でプロパティを宣言することができます。 通常、プロパティは、値または変数の単純なラッパーだけでするとプロパティが非単純な実装がある場合より明示的な方法と、自動の方法を使用してください。 プロパティを明示的に宣言するを使用して、 memberキーワードします。 この宣言構文に続いて、get メソッドおよび set メソッドを指定する構文を記述します。これらのメソッドは、accessorsとも呼ばれます。 「構文」セクションに示す、明示的な構文のさまざまなフォームは、読み取り/書き込み、読み取り専用、および書き込み専用プロパティが使用されます。 読み取り専用プロパティの場合は 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。 たとえば、次のクラスの型には、2 つの自動実装プロパティが含まれます。 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
出力
上記のコードの出力は、呼び出されるたびに、ExplicitProperty を変更するのに対し、値 AutoProperty の繰り返し呼び出されると変更されていないことを示しています。 明示的なプロパティの getter メソッドであるためするたびに、自動実装プロパティの式は評価されないことを示します。
注意
プロパティの初期化にも自動的に動作しない、基本クラス コンス トラクターでカスタム操作を実行するエンティティ フレームワーク (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