about_Classes_Methods

간단한 설명

PowerShell 클래스에 대한 메서드를 정의하는 방법을 설명합니다.

자세한 설명

메서드는 클래스가 수행할 수 있는 작업을 정의합니다. 메서드는 입력 데이터를 지정하는 매개 변수를 사용할 수 있습니다. 메서드는 항상 출력 형식을 정의합니다. 메서드가 출력을 반환하지 않는 경우 Void 출력 형식이 있어야 합니다. 메서드가 출력 형식을 명시적으로 정의하지 않으면 메서드의 출력 형식은 Void입니다.

클래스 메서드에서는 문에 지정된 개체를 제외하고 파이프라인으로 전송되는 개체가 return 없습니다. 코드에서 파이프라인에 대한 우발적인 출력은 없습니다.

참고 항목

이는 PowerShell 함수가 모든 것이 파이프라인으로 이동되는 출력을 처리하는 방식과 근본적으로 다릅니다.

클래스 메서드 내에서 오류 스트림에 기록된 확정되지 않은 오류는 전달되지 않습니다. 종료 오류를 노출하는 데 사용해야 throw 합니다. cmdlet을 Write-* 사용하면 클래스 메서드 내에서 PowerShell의 출력 스트림에 계속 쓸 수 있습니다. cmdlet은 호출 범위의 기본 설정 변수를 준수합니다 . 그러나 메서드가 문을 사용하여 개체만 출력할 수 있도록 cmdlet을 사용하지 Write-*return 않아야 합니다.

클래스 메서드는 자동 변수를 사용하여 $this 현재 클래스에 정의된 속성 및 기타 메서드에 액세스하여 클래스 개체의 현재 인스턴스를 참조할 수 있습니다. 자동 변수는 $this 정적 메서드에서 사용할 수 없습니다.

클래스 메서드는 숨겨진 특성과 정적 특성을 포함하여 다양한 특성을 가질 수 있습니다.

구문

클래스 메서드는 다음 구문을 사용합니다.

한 줄 구문

[[<attribute>]...] [hidden] [static] [<output-type>] <method-name> ([<method-parameters>]) { <body> }

여러 줄 구문

[[<attribute>]...]
[hidden]
[static]
[<output-type>] <method-name> ([<method-parameters>]) {
  <body>
}

예제

예제 1 - 최소 메서드 정의

ExampleCube1 클래스의 메서드는 GetVolume() 큐브의 볼륨을 반환합니다. 출력 형식을 부동 숫자로 정의하고 인스턴스의 Height, LengthWidth 속성을 곱한 결과를 반환합니다.

class ExampleCube1 {
    [float]   $Height
    [float]   $Length
    [float]   $Width

    [float] GetVolume() { return $this.Height * $this.Length * $this.Width }
}

$box = [ExampleCube1]@{
    Height = 2
    Length = 2
    Width  = 3
}

$box.GetVolume()
12

예제 2 - 매개 변수가 있는 메서드

이 메서드는 GeWeight() 큐브의 밀도에 대한 부동 숫자 입력을 사용하고 밀도를 곱한 볼륨으로 계산된 큐브의 가중치를 반환합니다.

class ExampleCube2 {
    [float]   $Height
    [float]   $Length
    [float]   $Width

    [float] GetVolume() { return $this.Height * $this.Length * $this.Width }
    [float] GetWeight([float]$Density) {
        return $this.GetVolume() * $Density
    }
}

$cube = [ExampleCube2]@{
    Height = 2
    Length = 2
    Width  = 3
}

$cube.GetWeight(2.5)
30

예제 3 - 출력이 없는 메서드

이 예제에서는 출력 형식을 Validate() System.Void사용하여 메서드를 정의합니다. 이 메서드는 출력을 반환하지 않습니다. 대신 유효성 검사가 실패하면 오류가 발생합니다. 메서드는 GetVolume() 큐브의 볼륨을 계산하기 전에 호출 Validate() 합니다. 유효성 검사에 실패하면 계산 전에 메서드가 종료됩니다.

class ExampleCube3 {
    [float]   $Height
    [float]   $Length
    [float]   $Width

    [float] GetVolume() {
        $this.Validate()

        return $this.Height * $this.Length * $this.Width
    }

    [void] Validate() {
        $InvalidProperties = @()
        foreach ($Property in @('Height', 'Length', 'Width')) {
            if ($this.$Property -le 0) {
                $InvalidProperties += $Property
            }
        }

        if ($InvalidProperties.Count -gt 0) {
            $Message = @(
                'Invalid cube properties'
                "('$($InvalidProperties -join "', '")'):"
                "Cube dimensions must all be positive numbers."
            ) -join ' '
            throw $Message
        }
    }
}

$Cube = [ExampleCube3]@{ Length = 1 ; Width = -1 }
$Cube

$Cube.GetVolume()
Height Length Width
------ ------ -----
  0.00   1.00 -1.00

Exception:
Line |
  20 |              throw $Message
     |              ~~~~~~~~~~~~~~
     | Invalid cube properties ('Height', 'Width'): Cube dimensions must
     | all be positive numbers.

HeightWidth 속성이 잘못되어 클래스가 현재 볼륨을 계산할 수 없으므로 메서드가 예외를 throw합니다.

예제 4 - 오버로드가 있는 정적 메서드

ExampleCube4 클래스는 두 오버로드가 있는 정적 메서드 GetVolume() 를 정의합니다. 첫 번째 오버로드에는 큐브의 차원에 대한 매개 변수와 메서드가 입력의 유효성을 검사해야 하는지 여부를 나타내는 플래그가 있습니다.

두 번째 오버로드는 숫자 입력만 포함합니다. 를 사용하여 첫 번째 오버로드를 $Static$true호출합니다. 두 번째 오버로드는 사용자가 항상 입력의 유효성을 엄격하게 검사할지 여부를 정의하지 않고도 메서드를 호출할 수 있는 방법을 제공합니다.

또한 클래스는 인스턴스(비정적) 메서드로 정의 GetVolume() 합니다. 이 메서드는 두 번째 정적 오버로드를 호출하여 인스턴스 GetVolume() 메서드가 출력 값을 반환하기 전에 항상 큐브의 차원의 유효성을 검사하도록 합니다.

class ExampleCube4 {
    [float]   $Height
    [float]   $Length
    [float]   $Width

    static [float] GetVolume(
        [float]$Height,
        [float]$Length,
        [float]$Width,
        [boolean]$Strict
    ) {
        $Signature = "[ExampleCube4]::GetVolume({0}, {1}, {2}, {3})"
        $Signature = $Signature -f $Height, $Length, $Width, $Strict
        Write-Verbose "Called $Signature"

        if ($Strict) {
            [ValidateScript({$_ -gt 0 })]$Height = $Height
            [ValidateScript({$_ -gt 0 })]$Length = $Length
            [ValidateScript({$_ -gt 0 })]$Width  = $Width
        }

        return $Height * $Length * $Width
    }

    static [float] GetVolume([float]$Height, [float]$Length, [float]$Width) {
        $Signature = "[ExampleCube4]::GetVolume($Height, $Length, $Width)"
        Write-Verbose "Called $Signature"

        return [ExampleCube4]::GetVolume($Height, $Length, $Width, $true)
    }

    [float] GetVolume() {
        Write-Verbose "Called `$this.GetVolume()"
        return [ExampleCube4]::GetVolume(
            $this.Height,
            $this.Length,
            $this.Width
        )
    }
}

$VerbosePreference = 'Continue'
$Cube = [ExampleCube4]@{ Height = 2 ; Length = 2 }
$Cube.GetVolume()
VERBOSE: Called $this.GetVolume()
VERBOSE: Called [ExampleCube4]::GetVolume(2, 2, 0)
VERBOSE: Called [ExampleCube4]::GetVolume(2, 2, 0, True)

MetadataError:
Line |
  19 |              [ValidateScript({$_ -gt 0 })]$Width  = $Width
     |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | The variable cannot be validated because the value 0 is not a valid
     | value for the Width variable.

메서드 정의의 자세한 내용은 초기 호출에서 정적 메서드를 호출하는 $this.GetVolume() 방법을 보여 줍니다.

Strict 매개 변수를 사용하여 정적 메서드를 볼륨에 대한 반환 0 으로 $false 직접 호출합니다.

[ExampleCube4]::GetVolume($Cube.Height, $Cube.Length, $Cube.Width, $false)
VERBOSE: Called [ExampleCube4]::GetVolume(2, 2, 0, False)
0

메서드 서명 및 오버로드

모든 클래스 메서드에는 메서드를 호출하는 방법을 정의하는 고유한 서명이 있습니다. 메서드의 출력 형식, 이름 및 매개 변수는 메서드 시그니처를 정의합니다.

클래스가 이름이 같은 메서드를 둘 이상 정의하는 경우 해당 메서드의 정의는 오버로드입니다. 메서드에 대한 오버로드에는 다른 매개 변수가 있어야 합니다. 출력 형식이 다르더라도 메서드는 동일한 매개 변수를 사용하여 두 개의 구현을 정의할 수 없습니다.

다음 클래스는 두 가지 메서드 Shuffle() 를 정의합니다 Deal(). 메서드는 Deal() 매개 변수가 없는 오버로드 두 개와 Count 매개 변수를 사용하는 오버로드를 정의합니다.

class CardDeck {
    [string[]]$Cards  = @()
    hidden [string[]]$Dealt  = @()
    hidden [string[]]$Suits  = @('Clubs', 'Diamonds', 'Hearts', 'Spades')
    hidden [string[]]$Values = 2..10 + @('Jack', 'Queen', 'King', 'Ace')

    CardDeck() {
        foreach($Suit in $this.Suits) {
            foreach($Value in $this.Values) {
                $this.Cards += "$Value of $Suit"
            }
        }
        $this.Shuffle()
    }

    [void] Shuffle() {
        $this.Cards = $this.Cards + $this.Dealt | Where-Object -FilterScript {
             -not [string]::IsNullOrEmpty($_)
        } | Get-Random -Count $this.Cards.Count
    }

    [string] Deal() {
        if ($this.Cards.Count -eq 0) { throw "There are no cards left." }

        $Card        = $this.Cards[0]
        $this.Cards  = $this.Cards[1..$this.Cards.Count]
        $this.Dealt += $Card

        return $Card
    }

    [string[]] Deal([int]$Count) {
        if ($Count -gt $this.Cards.Count) {
            throw "There are only $($this.Cards.Count) cards left."
        } elseif ($Count -lt 1) {
            throw "You must deal at least 1 card."
        }

        return (1..$Count | ForEach-Object { $this.Deal() })
    }
}

메서드 출력

기본적으로 메서드에는 출력이 없습니다. 메서드 서명에 Void 이외의 명시적 출력 형식이 포함된 경우 메서드는 해당 형식의 개체를 반환해야 합니다. 메서드는 키워드(keyword) 개체를 return 명시적으로 반환하는 경우를 제외하고는 출력을 내보내지 않습니다.

메서드 매개 변수

클래스 메서드는 메서드 본문에서 사용할 입력 매개 변수를 정의할 수 있습니다. 메서드 매개 변수는 괄호로 묶고 쉼표로 구분합니다. 빈 괄호는 메서드에 매개 변수가 필요하지 않음을 나타냅니다.

매개 변수는 한 줄 또는 여러 줄에 정의할 수 있습니다. 다음 블록은 메서드 매개 변수의 구문을 보여 줍니다.

([[<parameter-type>]]$<parameter-name>[, [[<parameter-type>]]$<parameter-name>])
(
    [[<parameter-type>]]$<parameter-name>[,
    [[<parameter-type>]]$<parameter-name>]
)

메서드 매개 변수를 강력하게 입력할 수 있습니다. 매개 변수를 입력하지 않으면 메서드는 해당 매개 변수에 대한 개체를 허용합니다. 매개 변수를 입력하면 메서드는 해당 매개 변수의 값을 올바른 형식으로 변환하려고 시도하며 입력을 변환할 수 없는 경우 예외를 throw합니다.

메서드 매개 변수는 기본값을 정의할 수 없습니다. 모든 메서드 매개 변수는 필수입니다.

메서드 매개 변수에는 다른 특성이 있을 수 없습니다. 이렇게 하면 메서드가 특성과 함께 매개 변수를 사용할 수 Validate* 없습니다. 유효성 검사 특성에 대한 자세한 내용은 about_Functions_Advanced_Parameters 참조하세요.

다음 패턴 중 하나를 사용하여 메서드 매개 변수에 유효성 검사를 추가할 수 있습니다.

  1. 필요한 유효성 검사 특성을 사용하여 매개 변수를 동일한 변수에 다시 할당합니다. 정적 메서드와 인스턴스 메서드 모두에 대해 작동합니다. 이 패턴의 예제는 예제 4를 참조하세요.
  2. 매개 변수에 ScriptMethod 대한 유효성 검사 특성을 직접 사용하는 값을 정의하는 데 사용합니다Update-TypeData. 인스턴스 메서드에 대해서만 작동합니다. 자세한 내용은 Update-TypeData 섹션을 사용하여 인스턴스 메서드 정의 섹션을 참조하세요.

메서드의 자동 변수

메서드에서 모든 자동 변수를 사용할 수 있는 것은 아닙니다. 다음 목록에는 PowerShell 클래스 메서드에서 사용할지 여부와 방법에 대한 자동 변수 및 제안이 포함되어 있습니다. 목록에 포함되지 않은 자동 변수는 클래스 메서드에서 사용할 수 없습니다.

  • $? - 정상적으로 액세스합니다.
  • $_ - 정상적으로 액세스합니다.
  • $args - 명시적 매개 변수 변수를 대신 사용합니다.
  • $ConsoleFileName - 대신 액세스 $Script:ConsoleFileName 합니다.
  • $Error - 정상적으로 액세스합니다.
  • $EnabledExperimentalFeatures - 대신 액세스 $Script:EnabledExperimentalFeatures 합니다.
  • $Event - 정상적으로 액세스합니다.
  • $EventArgs - 정상적으로 액세스합니다.
  • $EventSubscriber - 정상적으로 액세스합니다.
  • $ExecutionContext - 대신 액세스 $Script:ExecutionContext 합니다.
  • $false - 정상적으로 액세스합니다.
  • $foreach - 정상적으로 액세스합니다.
  • $HOME - 대신 액세스 $Script:HOME 합니다.
  • $Host - 대신 액세스 $Script:Host 합니다.
  • $input - 명시적 매개 변수 변수를 대신 사용합니다.
  • $IsCoreCLR - 대신 액세스 $Script:IsCoreCLR 합니다.
  • $IsLinux - 대신 액세스 $Script:IsLinux 합니다.
  • $IsMacOS - 대신 액세스 $Script:IsMacOS 합니다.
  • $IsWindows - 대신 액세스 $Script:IsWindows 합니다.
  • $LASTEXITCODE - 정상적으로 액세스합니다.
  • $Matches - 정상적으로 액세스합니다.
  • $MyInvocation - 정상적으로 액세스합니다.
  • $NestedPromptLevel - 정상적으로 액세스합니다.
  • $null - 정상적으로 액세스합니다.
  • $PID - 대신 액세스 $Script:PID 합니다.
  • $PROFILE - 대신 액세스 $Script:PROFILE 합니다.
  • $PSBoundParameters - 이 변수를 사용하지 마세요. cmdlet 및 함수용입니다. 클래스에서 사용하는 경우 예기치 않은 부작용이 발생할 수 있습니다.
  • $PSCmdlet - 이 변수를 사용하지 마세요. cmdlet 및 함수용입니다. 클래스에서 사용하는 경우 예기치 않은 부작용이 발생할 수 있습니다.
  • $PSCommandPath - 정상적으로 액세스합니다.
  • $PSCulture - 대신 액세스 $Script:PSCulture 합니다.
  • $PSEdition - 대신 액세스 $Script:PSEdition 합니다.
  • $PSHOME - 대신 액세스 $Script:PSHOME 합니다.
  • $PSItem - 정상적으로 액세스합니다.
  • $PSScriptRoot - 정상적으로 액세스합니다.
  • $PSSenderInfo - 대신 액세스 $Script:PSSenderInfo 합니다.
  • $PSUICulture - 대신 액세스 $Script:PSUICulture 합니다.
  • $PSVersionTable - 대신 액세스 $Script:PSVersionTable 합니다.
  • $PWD - 정상적으로 액세스합니다.
  • $Sender - 정상적으로 액세스합니다.
  • $ShellId - 대신 액세스 $Script:ShellId 합니다.
  • $StackTrace - 정상적으로 액세스합니다.
  • $switch - 정상적으로 액세스합니다.
  • $this - 정상적으로 액세스합니다. 클래스 메서드 $this 에서 항상 클래스의 현재 인스턴스입니다. 클래스 속성 및 메서드를 사용하여 액세스할 수 있습니다. 정적 메서드에서는 사용할 수 없습니다.
  • $true - 정상적으로 액세스합니다.

자동 변수에 대한 자세한 내용은 about_Automatic_Variables 참조하세요.

숨겨진 메서드

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

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

참고 항목

메서드에 대한 오버로드를 숨기면 해당 메서드가 IntelliSense, 완료 결과 및 기본 출력 Get-Member에서 제거됩니다.

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

정적 메서드

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

  • 클래스 인스턴스화와 관계없이 항상 사용할 수 있습니다.
  • 클래스의 모든 인스턴스에서 공유됩니다.
  • 항상 사용할 수 있습니다.
  • 클래스의 인스턴스 속성에 액세스할 수 없습니다. 정적 속성에만 액세스할 수 있습니다.
  • 전체 세션 범위에 대해 라이브입니다.

파생 클래스 메서드

클래스가 기본 클래스에서 파생되는 경우 기본 클래스 및 해당 오버로드의 메서드를 상속합니다. 숨겨진 메서드를 포함하여 기본 클래스에 정의된 모든 메서드 오버로드는 파생 클래스에서 사용할 수 있습니다.

파생 클래스는 클래스 정의에서 재정의하여 상속된 메서드 오버로드를 재정의할 수 있습니다. 오버로드를 재정의하려면 매개 변수 형식이 기본 클래스와 동일해야 합니다. 오버로드의 출력 형식은 다를 수 있습니다.

생성자와 달리 메서드는 구문을 사용하여 : base(<parameters>) 메서드에 대한 기본 클래스 오버로드를 호출할 수 없습니다. 파생 클래스에서 다시 정의된 오버로드는 기본 클래스에서 정의한 오버로드를 완전히 대체합니다.

다음 예제에서는 파생 클래스의 정적 메서드 및 인스턴스 메서드에 대한 동작을 보여 줍니다.

기본 클래스는 다음을 정의합니다.

  • 현재 시간을 반환하고 DaysAgo() 과거의 날짜를 반환하기 위한 정적 메서드 Now() 입니다.
  • 인스턴스 속성 TimeStampToString() 해당 속성의 문자열 표현을 반환하는 인스턴스 메서드입니다. 이렇게 하면 인스턴스가 문자열에 사용될 때 클래스 이름 대신 datetime 문자열로 변환됩니다.
  • 두 오버로드가 있는 인스턴스 메서드 SetTimeStamp() 입니다. 메서드가 매개 변수 없이 호출되면 TimeStamp현재 시간으로 설정합니다. DateTime을 사용하여 메서드를 호출하면 TimeStamp해당 값으로 설정합니다.
class BaseClass {
    static [datetime] Now() {
        return Get-Date
    }
    static [datetime] DaysAgo([int]$Count) {
        return [BaseClass]::Now().AddDays(-$Count)
    }

    [datetime] $TimeStamp = [BaseClass]::Now()

    [string] ToString() {
        return $this.TimeStamp.ToString()
    }

    [void] SetTimeStamp([datetime]$TimeStamp) {
        $this.TimeStamp = $TimeStamp
    }
    [void] SetTimeStamp() {
        $this.TimeStamp = [BaseClass]::Now()
    }
}

다음 블록은 BaseClass에서 파생된 클래스를 정의합니다.

  • DerivedClassA는 재정의 없이 BaseClass에서 상속됩니다.
  • DerivedClassBDaysAgo() DateTime 개체 대신 문자열 표현을 반환하도록 정적 메서드를 재정의합니다. 또한 타임스탬프를 ISO8601 날짜 문자열로 반환하도록 인스턴스 메서드를 재정 ToString() 의합니다.
  • DerivedClassC 는 매개 변수 없이 타임스탬프를 설정하여 현재 날짜보다 10일 전에 날짜를 설정하도록 메서드의 SetTimeStamp() 매개 변수 없는 오버로드를 재정의합니다.
class DerivedClassA : BaseClass     {}
class DerivedClassB : BaseClass     {
    static [string] DaysAgo([int]$Count) {
        return [BaseClass]::DaysAgo($Count).ToString('yyyy-MM-dd')
    }
    [string] ToString() {
        return $this.TimeStamp.ToString('yyyy-MM-dd')
    }
}
class DerivedClassC : BaseClass {
    [void] SetTimeStamp() {
        $this.SetTimeStamp([BaseClass]::Now().AddDays(-10))
    }
}

다음 블록은 정의된 클래스에 대한 정적 Now() 메서드의 출력을 보여 줍니다. 파생 클래스가 메서드의 기본 클래스 구현을 재정의하지 않으므로 출력은 모든 클래스에 대해 동일합니다.

"[BaseClass]::Now()     => $([BaseClass]::Now())"
"[DerivedClassA]::Now() => $([DerivedClassA]::Now())"
"[DerivedClassB]::Now() => $([DerivedClassB]::Now())"
"[DerivedClassC]::Now() => $([DerivedClassC]::Now())"
[BaseClass]::Now()     => 11/06/2023 09:41:23
[DerivedClassA]::Now() => 11/06/2023 09:41:23
[DerivedClassB]::Now() => 11/06/2023 09:41:23
[DerivedClassC]::Now() => 11/06/2023 09:41:23

다음 블록은 각 클래스의 DaysAgo() 정적 메서드를 호출합니다. 기본 구현을 오버로드하기 때문에 DerivedClassB의 출력만 다릅니다.

"[BaseClass]::DaysAgo(3)     => $([BaseClass]::DaysAgo(3))"
"[DerivedClassA]::DaysAgo(3) => $([DerivedClassA]::DaysAgo(3))"
"[DerivedClassB]::DaysAgo(3) => $([DerivedClassB]::DaysAgo(3))"
"[DerivedClassC]::DaysAgo(3) => $([DerivedClassC]::DaysAgo(3))"
[BaseClass]::DaysAgo(3)     => 11/03/2023 09:41:38
[DerivedClassA]::DaysAgo(3) => 11/03/2023 09:41:38
[DerivedClassB]::DaysAgo(3) => 2023-11-03
[DerivedClassC]::DaysAgo(3) => 11/03/2023 09:41:38

다음 블록은 각 클래스에 대한 새 인스턴스의 문자열 프레젠테이션을 보여 줍니다. DerivedClassB표현은 인스턴스 메서드를 ToString() 오버로드하기 때문에 다릅니다.

"`$base = [BaseClass]::New()     => $($base = [BaseClass]::New(); $base)"
"`$a    = [DerivedClassA]::New() => $($a = [DerivedClassA]::New(); $a)"
"`$b    = [DerivedClassB]::New() => $($b = [DerivedClassB]::New(); $b)"
"`$c    = [DerivedClassC]::New() => $($c = [DerivedClassC]::New(); $c)"
$base = [BaseClass]::New()     => 11/6/2023 9:44:57 AM
$a    = [DerivedClassA]::New() => 11/6/2023 9:44:57 AM
$b    = [DerivedClassB]::New() => 2023-11-06
$c    = [DerivedClassC]::New() => 11/6/2023 9:44:57 AM

다음 블록은 각 인스턴스에 SetTimeStamp() 대한 인스턴스 메서드를 호출하여 TimeStamp 속성을 특정 날짜로 설정합니다. 파생 클래스 중 어느 것도 메서드에 대한 매개 변수가 있는 오버로드를 재정의하지 않으므로 각 인스턴스의 날짜는 동일합니다.

[datetime]$Stamp = '2024-10-31'
"`$base.SetTimeStamp(`$Stamp) => $($base.SetTimeStamp($Stamp) ; $base)"
"`$a.SetTimeStamp(`$Stamp)    => $($a.SetTimeStamp($Stamp); $a)"
"`$b.SetTimeStamp(`$Stamp)    => $($b.SetTimeStamp($Stamp); $b)"
"`$c.SetTimeStamp(`$Stamp)    => $($c.SetTimeStamp($Stamp); $c)"
$base.SetTimeStamp($Stamp) => 10/31/2024 12:00:00 AM
$a.SetTimeStamp($Stamp)    => 10/31/2024 12:00:00 AM
$b.SetTimeStamp($Stamp)    => 2024-10-31
$c.SetTimeStamp($Stamp)    => 10/31/2024 12:00:00 AM

마지막 블록은 매개 변수 없이 호출 SetTimeStamp() 됩니다. 출력은 DerivedClassC 인스턴스의 값이 다른 인스턴스와 10일 전에 설정되었음을 보여 줍니다.

"`$base.SetTimeStamp() => $($base.SetTimeStamp() ; $base)"
"`$a.SetTimeStamp()    => $($a.SetTimeStamp(); $a)"
"`$b.SetTimeStamp()    => $($b.SetTimeStamp(); $b)"
"`$c.SetTimeStamp()    => $($c.SetTimeStamp(); $c)"
$base.SetTimeStamp() => 11/6/2023 9:53:58 AM
$a.SetTimeStamp()    => 11/6/2023 9:53:58 AM
$b.SetTimeStamp()    => 2023-11-06
$c.SetTimeStamp()    => 10/27/2023 9:53:58 AM

Update-TypeData를 사용하여 인스턴스 메서드 정의

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

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

class <ClassName> {
    static [hashtable[]] $MemberDefinitions = @(
        @{
            MemberName = '<MethodName>'
            MemberType = 'ScriptMethod'
            Value      = {
              param(<method-parameters>)

              <method-body>
            }
        }
    )

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

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

기본 매개 변수 값 및 유효성 검사 특성을 사용하여 메서드 정의

클래스 선언에 직접 정의된 메서드는 메서드 매개 변수에 대한 기본값 또는 유효성 검사 특성을 정의할 수 없습니다. 기본값 또는 유효성 검사 특성을 사용하여 클래스 메서드를 정의하려면 ScriptMethod 멤버로 정의해야 합니다.

이 예제에서 CardDeck 클래스는 Draw() 유효성 검사 특성과 Count 매개 변수의 기본값을 모두 사용하는 메서드를 정의합니다.

class CookieJar {
    [int] $Cookies = 12

    static [hashtable[]] $MemberDefinitions = @(
        @{
            MemberName = 'Eat'
            MemberType = 'ScriptMethod'
            Value      = {
                param(
                    [ValidateScript({ $_ -ge 1 -and $_ -le $this.Cookies })]
                    [int] $Count = 1
                )

                $this.Cookies -= $Count
                if ($Count -eq 1) {
                    "You ate 1 cookie. There are $($this.Cookies) left."
                } else {
                    "You ate $Count cookies. There are $($this.Cookies) left."
                }
            }
        }
    )

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

$Jar = [CookieJar]::new()
$Jar.Eat(1)
$Jar.Eat()
$Jar.Eat(20)
$Jar.Eat(6)
You ate 1 cookie. There are 11 left.

You ate 1 cookie. There are 10 left.

MethodInvocationException:
Line |
  36 |  $Jar.Eat(20)
     |  ~~~~~~~~~~~~
     | Exception calling "Eat" with "1" argument(s): "The attribute
     | cannot be added because variable Count with value 20 would no
     | longer be valid."

You ate 6 cookies. There are 4 left.

참고 항목

이 패턴은 유효성 검사 특성에 대해 작동하지만 예외가 잘못되어 특성을 추가할 수 없음을 참조합니다. 매개 변수 값을 명시적으로 검사 대신 의미 있는 오류를 발생 하려면 더 나은 사용자 환경이 될 수 있습니다. 이렇게 하면 사용자가 오류를 보는 이유와 오류에 대해 수행할 작업을 이해할 수 있습니다.

제한 사항

PowerShell 클래스 메서드에는 다음과 같은 제한 사항이 있습니다.

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

    해결 방법: 유효성 검사 특성을 사용하여 메서드 본문의 매개 변수를 다시 할당하거나 cmdlet을 사용하여 정적 생성자의 메서드를 Update-TypeData 정의합니다.

  • 메서드 매개 변수는 기본값을 정의할 수 없습니다. 매개 변수는 항상 필수입니다.

    해결 방법: cmdlet을 사용하여 정적 생성자에서 메서드를 Update-TypeData 정의합니다.

  • 메서드는 숨겨진 경우에도 항상 공용입니다. 클래스가 상속될 때 재정의할 수 있습니다.

    해결 방법: 없음.

  • 메서드의 오버로드가 숨겨지면 해당 메서드의 모든 오버로드도 숨김으로 처리됩니다.

    해결 방법: 없음.

참고 항목