プロパティ (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
解説
プロパティは、オブジェクト指向プログラミングにおける "has a" 関係を表し、オブジェクト インスタンスまたは型 (静的プロパティの場合) に関連付けられるデータを表します。
プロパティを宣言するには、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
プロパティのデータを保持するプライベート値を、バッキング ストアといいます。 他の言語と異なり、F# には、プロパティ用の暗黙のバッキング ストアを作成するためのしくみはありません。次に示すように、通常は変更可能な let バインディングを使用して、バッキング ストアを明示的に定義する必要があります。
type MyClass(x : string) =
let mutable myInternalValue = x
member this.MyProperty
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
プロパティは、クラス、構造体、判別共用体、レコード、インターフェイス、および型拡張のメンバーにすることができ、オブジェクト式でも定義できます。
プロパティには属性を適用できます。 プロパティに属性を適用するには、プロパティの前の独立した行で属性を記述します。 詳細については、「属性 (F#)」を参照してください。
既定では、プロパティはパブリックです。 プロパティには、アクセシビリティ修飾子も適用できます。 アクセシビリティ修飾子を適用するには、プロパティの名前の直前にアクセシビリティ修飾子を追加すると、get メソッドと set メソッドの両方に適用されます。また、アクセサーごとに異なるアクセシビリティが必要な場合は、get キーワードおよび set キーワードの前にアクセシビリティ修飾子を追加して適用します。 accessibility-modifier には、public、private、internal のいずれかを指定できます。 詳細については、「アクセス制御 (F#)」を参照してください。
プロパティの実装は、プロパティにアクセスするたびに実行されます。
静的プロパティとインスタンス プロパティ
プロパティには、静的なプロパティとインスタンス プロパティがあります。 静的プロパティは、インスタンスなしで呼び出すことができ、個別のオブジェクトではなく、型に関連付けられた値に使用されます。 静的プロパティの場合は、自己識別子を省略します。 インスタンス プロパティの場合は、自己識別子が必要です。
次の静的プロパティの定義は、プロパティのバッキング ストアである静的な 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