다음을 통해 공유


생성자(F#)

업데이트: 2010년 5월

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

클래스 개체 생성

클래스 형식의 개체에는 생성자가 있습니다. 이 생성자에는 두 가지 종류가 있습니다. 그중 하나는 형식 이름 바로 뒤에 매개 변수를 괄호로 묶어 표시하는 기본 생성자입니다. new 키워드를 사용하여 다른 선택적인 추가 생성자를 지정할 수도 있습니다. 이러한 추가 생성자는 모두 기본 생성자를 호출해야 합니다.

기본 생성자는 클래스 정의 시작 부분에 표시되는 let 및 do 바인딩을 포함합니다. let 바인딩은 클래스의 전용 필드와 메서드를 선언하고, do 바인딩은 코드를 실행합니다. 클래스 생성자의 let 바인딩에 대한 자세한 내용은 클래스의 let 바인딩(F#)을 참조하십시오. 생성자의 do 바인딩에 대한 자세한 내용은 클래스의 do 바인딩(F#)을 참조하십시오.

호출하려는 생성자가 기본 생성자이든 추가 생성자이든 상관없이 new 식을 사용하여 개체를 만들 수 있습니다. 이때 선택적 요소인 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이거나 그에 상응하는 값입니다. 구조체에 대해 정의하는 모든 생성자는 적어도 한 개 이상의 인수를 가져야 합니다. 그렇지 않으면 기본 생성자와 사용자가 정의하는 생성자가 서로 충돌할 수 있습니다.

또한 구조체에는 val 키워드를 사용하여 만든 필드가 포함되는 것이 일반적입니다. 원하는 경우 클래스에도 이러한 필드를 포함할 수 있습니다. 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 키워드(F#)를 참조하십시오.

생성자의 파생 작업 실행

클래스의 기본 생성자에서 do 바인딩의 코드를 실행할 수 있습니다. do 바인딩이 없는 추가 생성자에서 코드를 실행해야 하는 경우에는 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.

생성자의 자체 식별자

다른 멤버의 경우에는 각 멤버의 정의에 현재 개체의 이름을 제공합니다. 생성자 매개 변수 바로 뒤에 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 바인딩에 사용하거나 추가 생성자의 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")

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

개체를 만들기 위한 코드를 지정할 수 있을 뿐만 아니라, 형식 수준에서 초기화를 수행하기 위해 형식을 처음으로 사용하기 전에 실행되는 클래스 형식에서 정적 let 및 do 바인딩을 작성할 수도 있습니다. 자세한 내용은 클래스의 let 바인딩(F#)클래스의 do 바인딩(F#)을 참조하십시오.

참고 항목

개념

멤버(F#)

변경 기록

날짜

변경 내용

이유

2010년 5월

마지막 코드 예제의 문제가 수정되었습니다.

콘텐츠 버그 수정