다음을 통해 공유


생성자

이 문서에서는 생성자를 정의하고 사용하여 클래스 및 구조체 개체를 만들고 초기화하는 방법을 설명합니다.

클래스 개체 생성

클래스 형식의 개체에는 생성자가 있습니다. 생성자에는 두 가지 종류가 있습니다. 하나는 매개 변수가 형식 이름 바로 뒤의 괄호 안에 나타나는 기본 생성자입니다. 키워드(keyword) 사용하여 new 다른 선택적 추가 생성자를 지정합니다. 이러한 추가 생성자는 기본 생성자를 호출해야 합니다.

기본 생성자에는 let 클래스 정의의 시작 부분에 나타나는 바인딩 및 do 포함됩니다. 바인딩은 let 클래스의 프라이빗 필드와 메서드를 선언하고 바인딩은 do 코드를 실행합니다. 클래스 생성자의 바인딩에 대한 let 자세한 내용은 클래스의 바인딩을 참조 let 하세요. 생성자의 바인딩에 대한 do 자세한 내용은 클래스의 바인딩을 참조 do 하세요.

호출하려는 생성자가 기본 생성자인지 또는 추가 생성자인지에 관계없이 선택적 new 키워드(keyword) 포함하거나 사용하지 않고 식을 사용하여 new 개체를 만들 수 있습니다. 인수를 순서대로 나열하고 쉼표로 구분하고 괄호로 묶거나 명명된 인수와 값을 괄호로 사용하여 생성자 인수와 함께 개체를 초기화합니다. 명명된 생성자 인수를 사용하는 것처럼 속성 이름을 사용하고 값을 할당하여 개체를 생성하는 동안 개체에 속성을 설정할 수도 있습니다.

다음 코드는 생성자와 개체를 만드는 다양한 방법이 있는 클래스를 보여 줍니다.

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

출력은 다음과 같습니다.

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)

구조체 생성

구조체는 클래스의 모든 규칙을 따릅니다. 따라서 기본 생성자를 가질 수 있으며 , 를 사용하여 new추가 생성자를 제공할 수 있습니다. 그러나 구조체와 클래스 간에는 한 가지 중요한 차이점이 있습니다. 기본 생성자가 정의되지 않은 경우에도 구조체에는 매개 변수가 없는 생성자(즉, 인수가 없는 생성자)가 있을 수 있습니다. 매개 변수가 없는 생성자는 모든 필드를 해당 형식의 기본값(일반적으로 0 또는 해당 값)으로 초기화합니다. 구조체에 대해 정의하는 모든 생성자에는 매개 변수가 없는 생성자와 충돌하지 않도록 하나 이상의 인수가 있어야 합니다.

또한 구조체에는 키워드(keyword) 사용하여 val 만든 필드가 있는 경우가 많습니다. 클래스에도 이러한 필드가 있을 수 있습니다. 키워드(keyword) 사용하여 val 정의된 필드가 있는 구조체 및 클래스는 다음 코드와 같이 레코드 식을 사용하여 추가 생성자에서 초기화할 수도 있습니다.

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 워드를 참조하세요.

생성자에서 부작용 실행

클래스의 기본 생성자는 바인딩에서 do 코드를 실행할 수 있습니다. 그러나 바인딩 없이 추가 생성자에서 코드를 실행해야 하는 경우 어떻게 해야 할까 do 요? 이렇게 하려면 키워드(keyword) 사용합니다 then .

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

기본 생성자의 부작용은 계속 실행됩니다. 따라서 출력은 다음과 같습니다.

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

다른 dodo 생성자 대신 필요한 이유는 then 키워드(keyword) 추가 생성자의 본문에 있을 때 -returning 식을 구분하는 unit표준 의미가 있기 때문입니다. 기본 생성자의 컨텍스트에서만 특별한 의미가 있습니다.

생성자의 자체 식별자

다른 멤버에서는 각 멤버의 정의에 현재 개체의 이름을 제공합니다. 생성자 매개 변수 바로 다음에 키워드(keyword) 사용하여 as 클래스 정의의 첫 번째 줄에 자체 식별자를 배치할 수도 있습니다. 다음 예제에서는 이 구문을 보여 줍니다.

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 배치하여 자체 식별자를 정의할 수도 있습니다. 다음 예제에서는 이 구문을 보여 줍니다.

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

개체가 완전히 정의되기 전에 사용하려고 할 때 문제가 발생할 수 있습니다. 따라서 자체 식별자를 사용하면 컴파일러가 경고를 내보내고 개체가 초기화되기 전에 개체의 멤버에 액세스하지 못하도록 추가 검사 삽입할 수 있습니다. 기본 생성자의 바인딩 또는 do 추가 생성자의 키워드(keyword) 후에 then 자체 식별자만 사용해야 합니다.

자체 식별자의 이름은 을(를) 사용할 this필요가 없습니다. 유효한 식별자일 수 있습니다.

초기화 시 속성에 값 할당

생성자의 인수 목록에 양식 property = value 의 할당 목록을 추가하여 초기화 코드에서 클래스 개체의 속성에 값을 할당할 수 있습니다. 다음 코드 예제에 나와 있습니다.

 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)

이전 코드의 다음 버전은 하나의 생성자 호출에서 일반 인수, 선택적 인수 및 속성 설정의 조합을 보여 줍니다.

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

상속된 클래스의 생성자

생성자가 있는 기본 클래스에서 상속하는 경우 상속 절에서 해당 인수를 지정해야 합니다. 자세한 내용은 생성자 및 상속을 참조하세요.

정적 생성자 또는 형식 생성자

개체를 만들기 위한 코드를 지정하는 것 외에도 형식을 처음 사용하여 형식 수준에서 초기화를 수행하기 전에 실행되는 클래스 형식에서 정적 letdo 바인딩을 작성할 수 있습니다. 자세한 내용은 클래스의 바인딩 및 do 클래스의 바인딩을 참조 let 하세요.

참고 항목