コンストラクターConstructors

この記事では、コンストラクターを定義および使用して、クラスオブジェクトと構造体オブジェクトを作成および初期化する方法について説明します。This article describes how to define and use constructors to create and initialize class and structure objects.

クラスオブジェクトの構築Construction of class objects

クラス型のオブジェクトにはコンストラクターがあります。Objects of class types have constructors. コンストラクターには、次の2種類があります。There are two kinds of constructors. 1つはプライマリコンストラクターであり、パラメーターは型名の直後にかっこで囲まれています。One is the primary constructor, whose parameters appear in parentheses just after the type name. newキーワードを使用して、その他のオプションの追加コンストラクターを指定します。You specify other, optional additional constructors by using the new keyword. このような追加のコンストラクターは、プライマリコンストラクターを呼び出す必要があります。Any such additional constructors must call the primary constructor.

プライマリコンストラクターにはletdoクラス定義の先頭に表示されるバインディングとバインドが含まれています。The primary constructor contains let and do bindings that appear at the start of the class definition. バインディングletは、クラスのプライベートフィールドおよびメソッドを宣言しdoます。バインディングはコードを実行します。A let binding declares private fields and methods of the class; a do binding executes code. クラスコンストラクター内のletバインディングの詳細については、「 letクラスのバインディング」を参照してください。For more information about let bindings in class constructors, see let Bindings in Classes. コンストラクターでのdoバインディングの詳細については、「 doクラスのバインディング」を参照してください。For more information about do bindings in constructors, see do Bindings in Classes.

呼び出すコンストラクターがプライマリコンストラクターであるか、追加のコンストラクターであるかに関係なく、 new式を使用してオブジェクトを作成できます。これには、省略可能newなキーワードを指定するかどうかにかかわらず、式を使用します。Regardless of whether the constructor you want to call is a primary constructor or an additional constructor, you can create objects by using a new expression, with or without the optional new keyword. オブジェクトをコンストラクター引数と共に初期化するには、引数の順序を指定してコンマで区切り、かっこで囲むか、名前付き引数と値をかっこで囲んで指定します。You initialize your objects together with constructor arguments, either by listing the arguments in order and separated by commas and enclosed in parentheses, or by using named arguments and values in parentheses. また、プロパティ名を使用し、名前付きコンストラクター引数を使用するのと同じように値を割り当てることによって、オブジェクトの構築中にオブジェクトのプロパティを設定することもできます。You can also set properties on an object during the construction of the object by using the property names and assigning values just as you use named constructor arguments.

次のコードは、コンストラクターとオブジェクトを作成するさまざまな方法を持つクラスを示しています。The following code illustrates a class that has a constructor and various ways of creating objects:

// This class has a primary constructor that takes three arguments
// and an additional constructor that calls the primary constructor.
type MyClass(x0, y0, z0) =
    let mutable x = x0
    let mutable y = y0
    let mutable z = z0
    do
        printfn "Initialized object that has coordinates (%d, %d, %d)" x y z
    member this.X with get() = x and set(value) = x <- value
    member this.Y with get() = y and set(value) = y <- value
    member this.Z with get() = z and set(value) = z <- value
    new() = MyClass(0, 0, 0)

// Create by using the new keyword.
let myObject1 = new MyClass(1, 2, 3)
// Create without using the new keyword.
let myObject2 = MyClass(4, 5, 6)
// Create by using named arguments.
let myObject3 = MyClass(x0 = 7, y0 = 8, z0 = 9)
// Create by using the additional constructor.
let myObject4 = MyClass()

出力は次のとおりです。The output is as follows:

Initialized object that has coordinates (1, 2, 3)
Initialized object that has coordinates (4, 5, 6)
Initialized object that has coordinates (7, 8, 9)
Initialized object that has coordinates (0, 0, 0)

構造体の構築Construction of structures

構造体は、クラスのすべての規則に従います。Structures follow all the rules of classes. したがって、プライマリコンストラクターを持つことができます。また、を使用newして追加のコンストラクターを指定することもできます。Therefore, you can have a primary constructor, and you can provide additional constructors by using new. ただし、構造体とクラスには1つの重要な違いがあります。構造体には、プライマリコンストラクターが定義されていない場合でも、パラメーターなしのコンストラクター (つまり、引数なし) を含めることができます。However, there is one important difference between structures and classes: structures can have a parameterless constructor (that is, one with no arguments) even if no primary constructor is defined. パラメーターなしのコンストラクターは、すべてのフィールドをその型の既定値 (通常は0またはそれと等価) に初期化します。The parameterless constructor initializes all the fields to the default value for that type, usually zero or its equivalent. 構造体に対して定義するコンストラクターには、パラメーターなしのコンストラクターと競合しないように、少なくとも1つの引数が必要です。Any constructors that you define for structures must have at least one argument so that they do not conflict with the parameterless constructor.

また、多くの場合、構造体にはvalキーワードを使用して作成されたフィールドがあります。クラスにはこれらのフィールドも含まれます。Also, structures often have fields that are created by using the val keyword; classes can also have these fields. valキーワードを使用して定義されたフィールドを持つ構造体とクラスは、次のコードに示すように、レコード式を使用して追加のコンストラクターで初期化することもできます。Structures and classes that have fields defined by using the val keyword can also be initialized in additional constructors by using record expressions, as shown in the following code.

type MyStruct =
    struct
       val X : int
       val Y : int
       val Z : int
       new(x, y, z) = { X = x; Y = y; Z = z }
    end

let myStructure1 = new MyStruct(1, 2, 3)

詳細については、次を参照してください。明示的なフィールド:valキーワードします。For more information, see Explicit Fields: The val Keyword.

コンストラクターでの副作用の実行Executing side effects in constructors

クラスのプライマリコンストラクターは、 doバインディングでコードを実行できます。A primary constructor in a class can execute code in a do binding. ただし、 doバインドせずに、追加のコンストラクターでコードを実行する必要がある場合はどうすればよいでしょうか。However, what if you have to execute code in an additional constructor, without a do binding? これを行うには、 thenキーワードを使用します。To do this, you use the then keyword.

 // Executing side effects in the primary constructor and
// additional constructors.
type Person(nameIn : string, idIn : int) =
    let mutable name = nameIn
    let mutable id = idIn
    do printfn "Created a person object."
    member this.Name with get() = name and set(v) = name <- v
    member this.ID with get() = id and set(v) = id <- v
    new() =
        Person("Invalid Name", -1)
        then
            printfn "Created an invalid person object."

let person1 = new Person("Humberto Acevedo", 123458734)
let person2 = new Person()

プライマリコンストラクターの副作用は引き続き実行されます。The side effects of the primary constructor still execute. したがって、出力は次のようになります。Therefore, the output is as follows:

Created a person object.
Created a person object.
Created an invalid person object.

コンストラクター内の自己識別子Self identifiers in constructors

他のメンバーでは、各メンバーの定義で現在のオブジェクトの名前を指定します。In other members, you provide a name for the current object in the definition of each member. コンストラクターのパラメーターの直後にasキーワードを使用して、クラス定義の最初の行に自己識別子を配置することもできます。You can also put the self identifier on the first line of the class definition by using the as keyword immediately following the constructor parameters. この構文の例を次に示します。The following example illustrates this syntax.

type MyClass1(x) as this =
    // This use of the self identifier produces a warning - avoid.
    let x1 = this.X
    // This use of the self identifier is acceptable.
    do printfn "Initializing object with X =%d" this.X
    member this.X = x

追加のコンストラクターでは、コンストラクターパラメーターの直後にas句を配置することで、自己識別子を定義することもできます。In additional constructors, you can also define a self identifier by putting the as clause right after the constructor parameters. この構文の例を次に示します。The following example illustrates this syntax:

type MyClass2(x : int) =
    member this.X = x
    new() as this = MyClass2(0) then printfn "Initializing with X = %d" this.X

オブジェクトを完全に定義する前に使用しようとすると、問題が発生する可能性があります。Problems can occur when you try to use an object before it is fully defined. したがって、自己識別子を使用すると、コンパイラが警告を出力し、追加のチェックを挿入して、オブジェクトが初期化される前にオブジェクトのメンバーにアクセスしないようにすることができます。Therefore, uses of the self identifier can cause the compiler to emit a warning and insert additional checks to ensure the members of an object are not accessed before the object is initialized. 自己識別子は、プライマリコンストラクターのバインディング、 doまたは追加のコンストラクター内のthenキーワードの後にのみ使用してください。You should only use the self identifier in the do bindings of the primary constructor, or after the then keyword in additional constructors.

自己識別子の名前は、でthisある必要はありません。The name of the self identifier does not have to be this. 任意の有効な識別子を指定できます。It can be any valid identifier.

初期化時のプロパティへの値の割り当てAssigning values to properties at initialization

コンストラクターの引数リストにフォームproperty = valueの割り当ての一覧を追加することにより、初期化コードでクラスオブジェクトのプロパティに値を割り当てることができます。You can assign values to the properties of a class object in the initialization code by appending a list of assignments of the form property = value to the argument list for a constructor. これを次のコード例に示します。This is shown in the following code example:

 type Account() =
    let mutable balance = 0.0
    let mutable number = 0
    let mutable firstName = ""
    let mutable lastName = ""
    member this.AccountNumber
       with get() = number
       and set(value) = number <- value
    member this.FirstName
       with get() = firstName
       and set(value) = firstName <- value
    member this.LastName
       with get() = lastName
       and set(value) = lastName <- value
    member this.Balance
       with get() = balance
       and set(value) = balance <- value
    member this.Deposit(amount: float) = this.Balance <- this.Balance + amount
    member this.Withdraw(amount: float) = this.Balance <- this.Balance - amount


let account1 = new Account(AccountNumber=8782108,
                           FirstName="Darren", LastName="Parker",
                           Balance=1543.33)

次のバージョンの前のコードは、通常の引数、省略可能な引数、およびプロパティ設定を1つのコンストラクター呼び出しで組み合わせる方法を示しています。The following version of the previous code illustrates the combination of ordinary arguments, optional arguments, and property settings in one constructor call:

type Account(accountNumber : int, ?first: string, ?last: string, ?bal : float) =
   let mutable balance = defaultArg bal 0.0
   let mutable number = accountNumber
   let mutable firstName = defaultArg first ""
   let mutable lastName = defaultArg last ""
   member this.AccountNumber
      with get() = number
      and set(value) = number <- value
   member this.FirstName
      with get() = firstName
      and set(value) = firstName <- value
   member this.LastName
      with get() = lastName
      and set(value) = lastName <- value
   member this.Balance
      with get() = balance
      and set(value) = balance <- value
   member this.Deposit(amount: float) = this.Balance <- this.Balance + amount
   member this.Withdraw(amount: float) = this.Balance <- this.Balance - amount


let account1 = new Account(8782108, bal = 543.33,
                          FirstName="Raman", LastName="Iyer")

継承されたクラスのコンストラクターConstructors in inherited class

コンストラクターを持つ基底クラスから継承する場合は、inherit 句で引数を指定する必要があります。When inheriting from a base class that has a constructor, you must specify its arguments in the inherit clause. 詳細については、「コンストラクターと継承」を参照してください。For more information, see Constructors and inheritance.

静的コンストラクターまたは型コンストラクターStatic constructors or type constructors

オブジェクトを作成するためのコードを指定するletだけdoでなく、型を最初に使用して型レベルで初期化を実行する前に実行されるクラス型で静的およびバインディングを作成することもできます。In addition to specifying code for creating objects, static let and do bindings can be authored in class types that execute before the type is first used to perform initialization at the type level. 詳細については、「クラスと doバインド letのバインド」を参照してください。For more information, see let Bindings in Classes and do Bindings in Classes.

関連項目See also