about_Classes_Constructors

간단한 설명

PowerShell 클래스에 대한 생성자를 정의하는 방법을 설명합니다.

자세한 설명

생성자를 사용하면 클래스의 인스턴스를 만들 때 기본값을 설정하고 개체 논리의 유효성을 검사할 수 있습니다. 생성자의 이름은 클래스와 같습니다. 생성자에는 새 개체의 데이터 멤버를 초기화하는 매개 변수가 있을 수 있습니다.

PowerShell 클래스 생성자는 클래스에서 특수 메서드로 정의됩니다. 다음과 같은 예외를 제외하고 PowerShell 클래스 메서드와 동일하게 동작합니다.

  • 생성자에는 출력 형식이 없습니다. 키워드(keyword) 사용할 return 수 없습니다.
  • 생성자는 항상 클래스와 동일한 이름을 갖습니다.
  • 생성자를 직접 호출할 수 없습니다. 인스턴스를 만들 때만 실행됩니다.
  • 생성자는 cmdlet의 출력에 Get-Member 표시되지 않습니다.

PowerShell 클래스 메서드에 대한 자세한 내용은 about_Classes_Methods 참조하세요.

클래스에는 정의된 0개 이상의 생성자가 있을 수 있습니다. 생성자가 정의되지 않은 경우 클래스에 매개 변수가 없는 기본 생성자가 제공됩니다. 이 생성자는 모든 멤버를 기본값으로 초기화합니다. 개체 형식 및 문자열에는 null 값이 지정됩니다. 생성자를 정의할 때는 기본 매개 변수가 없는 생성자가 만들어지지 않습니다. 필요한 경우 매개 변수가 없는 생성자를 만듭니다.

매개 변수가 없는 정적 생성자를 정의할 수도 있습니다.

구문

클래스 생성자는 다음 구문을 사용합니다.

기본 생성자 구문

<class-name> () [: base([<params>])] {
    <body>
}

정적 생성자 구문

static <class-name> () [: base([<params>])] {
    <body>
}

매개 변수가 있는 생성자 구문(한 줄)

<class-name> ([[<parameter-type>]$<parameter-name>[, [<parameter-type>]$<parameter-name>...]]) [: base([<params>])] {
    <body>
}

매개 변수가 있는 생성자 구문(여러 줄)

<class-name> (
    [<parameter-type>]$<parameter-name>[,
    [<parameter-type>]$<parameter-name>...]
) [: base([<params>])] {
    <body>
}

예제

예제 1 - 기본 생성자를 사용하여 클래스 정의

ExampleBook1 클래스는 생성자를 정의하지 않습니다. 대신 자동 기본 생성자를 사용합니다.

class ExampleBook1 {
    [string]   $Name
    [string]   $Author
    [int]      $Pages
    [datetime] $PublishedOn
}

[ExampleBook1]::new()
Name Author Pages PublishedOn
---- ------ ----- -----------
                0 1/1/0001 12:00:00 AM

참고 항목

Name 및 Author 속성의 기본값은 $null 참조 형식인 문자열로 입력되기 때문입니다. 다른 속성은 값 형식 속성이므로 정의된 형식의 기본값을 갖습니다. 속성 의 기본값에 대한 자세한 내용은 about_Classes_Properties "기본 속성 값"을 참조하세요.

예제 2 - 기본 생성자 재정의

ExampleBook2는 기본 생성자를 명시적으로 정의하고 PublishedOn값을 현재 날짜로 설정하고 Pages1.로 설정합니다.

class ExampleBook2 {
    [string]   $Name
    [string]   $Author
    [int]      $Pages
    [datetime] $PublishedOn

    ExampleBook2() {
        $this.PublishedOn = (Get-Date).Date
        $this.Pages       = 1
    }
}

[ExampleBook2]::new()
Name Author Pages PublishedOn
---- ------ ----- -----------
                1 11/1/2023 12:00:00 AM

예제 3 - 생성자 오버로드 정의

ExampleBook3 클래스는 세 가지 생성자 오버로드를 정의하여 사용자가 모든 속성 값을 전달하고 책과 저자의 이름을 전달하여 해시 테이블에서 클래스의 인스턴스를 만들 수 있도록 합니다. 클래스는 기본 생성자를 정의하지 않습니다.

class ExampleBook3 {
    [string]   $Name
    [string]   $Author
    [int]      $Pages
    [datetime] $PublishedOn

    ExampleBook3([hashtable]$Info) {
        switch ($Info.Keys) {
            'Name'        { $this.Name        = $Info.Name }
            'Author'      { $this.Author      = $Info.Author }
            'Pages'       { $this.Pages       = $Info.Pages }
            'PublishedOn' { $this.PublishedOn = $Info.PublishedOn }
        }
    }

    ExampleBook3(
        [string]   $Name,
        [string]   $Author,
        [int]      $Pages,
        [datetime] $PublishedOn
    ) {
        $this.Name        = $Name
        $this.Author      = $Author
        $this.Pages       = $Pages
        $this.PublishedOn = $PublishedOn
    }

    ExampleBook3([string]$Name, [string]$Author) {
        $this.Name   = $Name
        $this.Author = $Author
    }
}

[ExampleBook3]::new(@{
    Name        = 'The Hobbit'
    Author      = 'J.R.R. Tolkien'
    Pages       = 310
    PublishedOn = '1937-09-21'
})
[ExampleBook3]::new('The Hobbit', 'J.R.R. Tolkien', 310, '1937-09-21')
[ExampleBook3]::new('The Hobbit', 'J.R.R. Tolkien')
[ExampleBook3]::new()
Name       Author         Pages PublishedOn
----       ------         ----- -----------
The Hobbit J.R.R. Tolkien   310 9/21/1937 12:00:00 AM
The Hobbit J.R.R. Tolkien   310 9/21/1937 12:00:00 AM
The Hobbit J.R.R. Tolkien     0 1/1/0001 12:00:00 AM

MethodException:
Line |
  42 |  [ExampleBook3]::new()
     |  ~~~~~~~~~~~~~~~~~~~~~
     | Cannot find an overload for "new" and the argument count: "0".

기본 생성자를 호출하면 메서드 예외가 반환됩니다. 자동 기본 생성자는 클래스가 생성자를 정의하지 않는 경우에만 클래스에 대해 정의됩니다. ExampleBook3은 여러 오버로드를 정의하므로 기본 생성자는 클래스에 자동으로 추가되지 않습니다.

예제 4 - 공유 메서드를 사용하여 생성자 연결

이 예제에서는 생성자에 대해 재사용 가능한 공유 코드를 작성하는 방법을 보여줍니다. PowerShell 클래스는 생성자 체인을 사용할 수 없으므로 이 예제 클래스는 메서드를 Init() 대신 정의합니다. 해당 메서드는 몇 가지 오버로드를 갖고 있습니다. 매개 변수가 적은 오버로드는 지정되지 않은 매개 변수에 대한 기본값을 사용하여 더 명시적인 오버로드를 호출합니다.

class ExampleBook4 {
    [string]   $Name
    [string]   $Author
    [datetime] $PublishedOn
    [int]      $Pages

    ExampleBook4() {
        $this.Init()
    }
    ExampleBook4([string]$Name) {
        $this.Init($Name)
    }
    ExampleBook4([string]$Name, [string]$Author) {
        $this.Init($Name, $Author)
    }
    ExampleBook4([string]$Name, [string]$Author, [datetime]$PublishedOn) {
        $this.Init($Name, $Author, $PublishedOn)
    }
    ExampleBook4(
      [string]$Name,
      [string]$Author,
      [datetime]$PublishedOn,
      [int]$Pages
    ) {
        $this.Init($Name, $Author, $PublishedOn, $Pages)
    }

    hidden Init() {
        $this.Init('Unknown')
    }
    hidden Init([string]$Name) {
        $this.Init($Name, 'Unknown')
    }
    hidden Init([string]$Name, [string]$Author) {
        $this.Init($Name, $Author, (Get-Date).Date)
    }
    hidden Init([string]$Name, [string]$Author, [datetime]$PublishedOn) {
        $this.Init($Name, $Author, $PublishedOn, 1)
    }
    hidden Init(
        [string]$Name,
        [string]$Author,
        [datetime]$PublishedOn,
        [int]$Pages
      ) {
        $this.Name        = $Name
        $this.Author      = $Author
        $this.PublishedOn = $PublishedOn
        $this.Pages       = $Pages
    }
}

[ExampleBook4]::new()
[ExampleBook4]::new('The Hobbit')
[ExampleBook4]::new('The Hobbit', 'J.R.R. Tolkien')
[ExampleBook4]::new('The Hobbit', 'J.R.R. Tolkien', (Get-Date '1937-9-21'))
[ExampleBook4]::new(
    'The Hobbit',
    'J.R.R. Tolkien',
    (Get-Date '1937-9-21'),
    310
)
Name       Author         PublishedOn           Pages
----       ------         -----------           -----
Unknown    Unknown        11/1/2023 12:00:00 AM     1
The Hobbit Unknown        11/1/2023 12:00:00 AM     1
The Hobbit J.R.R. Tolkien 11/1/2023 12:00:00 AM     1
The Hobbit J.R.R. Tolkien 9/21/1937 12:00:00 AM     1
The Hobbit J.R.R. Tolkien 9/21/1937 12:00:00 AM   310

예제 5 - 파생 클래스 생성자

다음 예제에서는 기본 클래스 및 기본 클래스에서 상속 하는 파생된 클래스에 대 한 정적, 기본 및 매개 변수가 있는 생성자를 정의 하는 클래스를 사용 합니다.

class BaseExample {
    static [void] DefaultMessage([type]$Type) {
        Write-Verbose "[$($Type.Name)] default constructor"
    }

    static [void] StaticMessage([type]$Type) {
        Write-Verbose "[$($Type.Name)] static constructor"
    }

    static [void] ParamMessage([type]$Type, [object]$Value) {
        Write-Verbose "[$($Type.Name)] param constructor ($Value)"
    }

    static BaseExample() { [BaseExample]::StaticMessage([BaseExample])  }
    BaseExample()        { [BaseExample]::DefaultMessage([BaseExample]) }
    BaseExample($Value)  { [BaseExample]::ParamMessage([BaseExample], $Value) }
}

class DerivedExample : BaseExample {
    static DerivedExample() { [BaseExample]::StaticMessage([DerivedExample])  }
           DerivedExample() { [BaseExample]::DefaultMessage([DerivedExample]) }

    DerivedExample([int]$Number) : base($Number) {
        [BaseExample]::ParamMessage([DerivedExample], $Number)
    }
    DerivedExample([string]$String) {
        [BaseExample]::ParamMessage([DerivedExample], $String)
    }
}

다음 블록은 기본 클래스 생성자를 호출하기 위한 자세한 메시지입니다. 정적 생성자 메시지는 클래스의 인스턴스를 처음 만들 때만 내보내집니다.

PS> $VerbosePreference = 'Continue'
PS> $b = [BaseExample]::new()

VERBOSE: [BaseExample] static constructor
VERBOSE: [BaseExample] default constructor

PS> $b = [BaseExample]::new()

VERBOSE: [BaseExample] default constructor

PS> $b = [BaseExample]::new(1)

VERBOSE: [BaseExample] param constructor (1)

다음 블록은 새 세션에서 파생 클래스 생성자를 호출하기 위한 자세한 메시지입니다. 파생 클래스 생성자가 처음 호출될 때 기본 클래스 및 파생 클래스에 대한 정적 생성자가 호출됩니다. 이러한 생성자는 세션에서 다시 호출되지 않습니다. 기본 클래스의 생성자는 항상 파생 클래스의 생성자 앞에 실행됩니다.

PS> $VerbosePreference = 'Continue'
PS> $c = [DerivedExample]::new()

VERBOSE: [BaseExample] static constructor
VERBOSE: [DerivedExample] static constructor
VERBOSE: [BaseExample] default constructor
VERBOSE: [DerivedExample] default constructor

PS> $c = [DerivedExample]::new()

VERBOSE: [BaseExample] default constructor
VERBOSE: [DerivedExample] default constructor

PS> $c = [DerivedExample]::new(1)

VERBOSE: [BaseExample] param constructor (1)
VERBOSE: [DerivedExample] param constructor (1)

PS> $c = [DerivedExample]::new('foo')

VERBOSE: [BaseExample] default constructor
VERBOSE: [DerivedExample] param constructor (foo)

생성자 실행 순서 지정

클래스가 인스턴스화되면 하나 이상의 생성자에 대한 코드가 실행됩니다.

다른 클래스에서 상속되지 않는 클래스의 경우 순서는 다음과 같습니다.

  1. 클래스의 정적 생성자입니다.
  2. 클래스에 적용 가능한 생성자 오버로드입니다.

다른 클래스에서 상속되는 파생 클래스의 경우 순서는 다음과 같습니다.

  1. 기본 클래스의 정적 생성자입니다.
  2. 파생 클래스의 정적 생성자입니다.
  3. 파생 클래스 생성자가 명시적으로 기본 생성자 오버로드를 호출하는 경우 기본 클래스에 대해 해당 생성자를 실행합니다. 기본 생성자를 명시적으로 호출하지 않으면 기본 클래스에 대한 기본 생성자를 실행합니다.
  4. 파생 클래스에 적용 가능한 생성자 오버로드입니다.

모든 경우에 정적 생성자는 세션에서 한 번만 실행됩니다.

생성자 동작 및 순서 지정의 예는 예제 5를 참조하세요.

숨겨진 생성자

키워드(keyword) 사용하여 선언하여 hidden 클래스의 생성자를 숨길 수 있습니다. 숨겨진 클래스 생성자는 다음과 같습니다.

  • 클래스의 기본 출력에 포함되지 않습니다.
  • cmdlet에서 반환 Get-Member 하는 클래스 멤버 목록에 포함되지 않습니다. 숨겨진 속성을 Get-Member표시하려면 Force 매개 변수를 사용합니다.
  • 숨겨진 속성을 정의하는 클래스에서 완료가 발생하지 않는 한 탭 완성 또는 IntelliSense에 표시되지 않습니다.
  • 클래스의 공용 멤버입니다. 액세스하고 수정할 수 있습니다. 속성을 숨기면 비공개로 만들 수 없습니다. 이전 지점에 설명된 대로 속성만 숨깁니다.

참고 항목

생성자를 new() 숨기면 IntelliSense 및 완료 결과에서 옵션이 제거됩니다.

키워드(keyword) 대한 hidden 자세한 내용은 about_Hidden 참조하세요.

정적 생성자

키워드(keyword) 사용하여 생성자를 선언하여 클래스의 인스턴스 대신 클래스 자체에 속하는 생성자를 static 정의할 수 있습니다. 정적 클래스 생성자:

  • 세션에서 클래스의 인스턴스를 처음 만들 때만 호출합니다.
  • 매개 변수를 사용할 수 없습니다.
  • 변수를 사용하여 인스턴스 속성 또는 메서드에 $this 액세스할 수 없습니다.

파생 클래스에 대한 생성자

클래스가 다른 클래스에서 상속되는 경우 생성자는 키워드(keyword) 사용하여 기본 클래스에서 생성자를 호출할 base 수 있습니다. 파생 클래스가 기본 클래스에서 생성자를 명시적으로 호출하지 않으면 기본 클래스에 대한 기본 생성자를 대신 호출합니다.

기본이 아닌 기본 생성자를 호출하려면 생성자 매개 변수 뒤와 본문 블록 앞에 추가 : base(<parameters>) 합니다.

class <derived-class> : <base-class> {
    <derived-class>(<derived-parameters>) : <base-class>(<base-parameters>) {
        # initialization code
    }
}

기본 클래스 생성자를 호출하는 생성자를 정의할 때 매개 변수는 다음 항목 중 어느 것이든 될 수 있습니다.

  • 파생 클래스 생성자에 대한 매개 변수의 변수입니다.
  • 모든 정적 값입니다.
  • 매개 변수 형식의 값으로 계산되는 식입니다.

파생 클래스의 생성자 예제는 예제 5를 참조하세요.

연결 생성자

C#과 달리 PowerShell 클래스 생성자는 구문과 체인 : this(<parameters>) 을 사용할 수 없습니다. 코드 중복을 줄이려면 동일한 효과에 대해 여러 오버로드가 있는 숨겨진 Init() 메서드를 사용합니다. 예제 4 에서는 이 패턴을 사용하는 클래스를 보여 줍니다.

Update-TypeData를 사용하여 인스턴스 속성 및 메서드 추가

클래스 정의에서 직접 속성 및 메서드를 선언하는 것 외에도 cmdlet을 사용하여 정적 생성자의 클래스 인스턴스에 대한 속성을 정의할 Update-TypeData 수 있습니다.

이 코드 조각을 패턴의 시작점으로 사용합니다. 필요에 따라 자리 표시자 텍스트를 꺾쇠 괄호로 바꿉니다.

class <class-name> {
    static [hashtable[]] $MemberDefinitions = @(
        @{
            Name       = '<member-name>'
            MemberType = '<member-type>'
            Value      = <member-definition>
        }
    )

    static <class-name>() {
        $TypeName = [<class-name>].Name
        foreach ($Definition in [<class-name>]::MemberDefinitions) {
            Update-TypeData -TypeName $TypeName @Definition
        }
    }
}

cmdlet은 Add-Member 비정적 생성자의 클래스에 속성과 메서드를 추가할 수 있지만 생성자가 호출될 때마다 cmdlet이 실행됩니다. 정적 생성자에서 사용하면 Update-TypeData 클래스에 멤버를 추가하는 코드가 세션에서 한 번만 실행하면 됩니다.

읽기 전용 속성과 같이 정의 Update-TypeData할 수 없는 경우에만 비정적 생성자의 클래스에 속성을 추가합니다.

인스턴스 메서드Update-TypeData를 정의하는 방법에 대한 자세한 내용은 about_Classes_Methods 참조하세요. 인스턴스 속성을 Update-TypeData정의하는 방법에 대한 자세한 내용은 about_Classes_Properties 참조하세요.

제한 사항

PowerShell 클래스 생성자에는 다음과 같은 제한 사항이 있습니다.

  • 생성자 체인은 구현되지 않습니다.

    해결 방법: 숨겨진 Init() 메서드를 정의하고 생성자 내에서 호출합니다.

  • 생성자 매개 변수는 유효성 검사 특성을 비롯한 특성을 사용할 수 없습니다.

    해결 방법: 유효성 검사 특성을 사용하여 생성자 본문의 매개 변수를 다시 할당합니다.

  • 생성자 매개 변수는 기본값을 정의할 수 없습니다. 매개 변수는 항상 필수입니다.

    해결 방법: 없음.

  • 생성자의 오버로드가 숨겨지면 생성자에 대한 모든 오버로드도 숨김으로 처리됩니다.

    해결 방법: 없음.

참고 항목