클래스 정보
간단한 설명
클래스를 사용하여 사용자 지정 형식을 만드는 방법을 설명합니다.
자세한 설명입니다.
PowerShell 5.0은 클래스 및 기타 사용자 정의 형식을 정의하는 공식 구문을 추가합니다. 클래스를 추가하면 개발자와 IT 전문가가 광범위한 사용 사례에 대해 PowerShell을 수용할 수 있습니다. PowerShell 아티팩트 개발을 간소화하고 관리 표면의 적용 범위를 가속화합니다.
클래스 선언은 런타임에 개체의 인스턴스를 만드는 데 사용되는 청사진입니다. 클래스를 정의할 때 클래스 이름은 형식의 이름입니다. 예를 들어 Device라는 클래스를 선언하고 변수 $dev
를 Device의 새 instance 초기화하는 경우 은 Device$dev
형식의 개체 또는 instance. 디바이스의 각 instance 속성에 서로 다른 값을 가질 수 있습니다.
지원되는 시나리오
- 클래스, 속성, 메서드, 상속 등과 같은 친숙한 개체 지향 프로그래밍 의미 체계를 사용하여 PowerShell에서 사용자 지정 형식을 정의합니다.
- PowerShell 언어를 사용하여 형식을 디버그합니다.
- 공식 메커니즘을 사용하여 예외를 생성하고 처리합니다.
- PowerShell 언어를 사용하여 DSC 리소스 및 관련 형식을 정의합니다.
Syntax
클래스는 다음 구문을 사용하여 선언됩니다.
class <class-name> [: [<base-class>][,<interface-list]] {
[[<attribute>] [hidden] [static] <property-definition> ...]
[<class-name>([<constructor-argument-list>])
{<constructor-statement-list>} ...]
[[<attribute>] [hidden] [static] <method-definition> ...]
}
클래스는 다음 구문 중 하나를 사용하여 인스턴스화됩니다.
[$<variable-name> =] New-Object -TypeName <class-name> [
[-ArgumentList] <constructor-argument-list>]
[$<variable-name> =] [<class-name>]::new([<constructor-argument-list>])
참고
구문을 사용하는 [<class-name>]::new(
경우 클래스 이름 주위의 대괄호는 필수입니다. 대괄호는 PowerShell에 대한 형식 정의를 신호로 표시합니다.
예제 구문 및 사용법
이 예제에서는 사용 가능한 클래스를 만드는 데 필요한 최소 구문을 보여줍니다.
class Device {
[string]$Brand
}
$dev = [Device]::new()
$dev.Brand = "Microsoft"
$dev
Brand
-----
Microsoft
클래스 속성
속성은 클래스 scope 선언된 변수입니다. 속성은 모든 기본 제공 형식이거나 다른 클래스의 instance 수 있습니다. 클래스는 속성 수에 제한이 없습니다.
단순 속성이 있는 예제 클래스
class Device {
[string]$Brand
[string]$Model
[string]$VendorSku
}
$device = [Device]::new()
$device.Brand = "Microsoft"
$device.Model = "Surface Pro 4"
$device.VendorSku = "5072641000"
$device
Brand Model VendorSku
----- ----- ---------
Microsoft Surface Pro 4 5072641000
클래스 속성의 복합 형식 예제
이 예제에서는 Device 클래스를 사용하여 빈 Rack 클래스를 정의합니다. 다음 예제에서는 디바이스를 랙에 추가하는 방법과 미리 로드된 랙으로 시작하는 방법을 보여 줍니다.
class Device {
[string]$Brand
[string]$Model
[string]$VendorSku
}
class Rack {
[string]$Brand
[string]$Model
[string]$VendorSku
[string]$AssetId
[Device[]]$Devices = [Device[]]::new(8)
}
$rack = [Rack]::new()
$rack
Brand :
Model :
VendorSku :
AssetId :
Devices : {$null, $null, $null, $null...}
클래스 메서드
메서드는 클래스가 수행할 수 있는 작업을 정의합니다. 메서드는 입력 데이터를 제공하는 매개 변수를 취할 수 있습니다. 메서드는 출력을 반환할 수 있습니다. 메서드에서 반환되는 데이터는 정의된 데이터 형식일 수 있습니다.
속성 및 메서드가 있는 예제 단순 클래스
랙 클래스를 확장하여 디바이스를 추가하거나 제거할 수 있습니다.
class Device {
[string]$Brand
[string]$Model
[string]$VendorSku
[string]ToString(){
return ("{0}|{1}|{2}" -f $this.Brand, $this.Model, $this.VendorSku)
}
}
class Rack {
[int]$Slots = 8
[string]$Brand
[string]$Model
[string]$VendorSku
[string]$AssetId
[Device[]]$Devices = [Device[]]::new($this.Slots)
[void] AddDevice([Device]$dev, [int]$slot){
## Add argument validation logic here
$this.Devices[$slot] = $dev
}
[void]RemoveDevice([int]$slot){
## Add argument validation logic here
$this.Devices[$slot] = $null
}
[int[]] GetAvailableSlots(){
[int]$i = 0
return @($this.Devices.foreach{ if($_ -eq $null){$i}; $i++})
}
}
$rack = [Rack]::new()
$surface = [Device]::new()
$surface.Brand = "Microsoft"
$surface.Model = "Surface Pro 4"
$surface.VendorSku = "5072641000"
$rack.AddDevice($surface, 2)
$rack
$rack.GetAvailableSlots()
Slots : 8
Brand :
Model :
VendorSku :
AssetId :
Devices : {$null, $null, Microsoft|Surface Pro 4|5072641000, $null...}
0
1
3
4
5
6
7
클래스 메서드의 출력
메서드에는 반환 형식이 정의되어야 합니다. 메서드가 출력을 반환하지 않으면 출력 형식은 이어야 [void]
합니다.
클래스 메서드에서는 문에 언급된 개체를 제외하고 파이프라인으로 전송되는 개체가 return
없습니다. 코드에서 파이프라인에 실수로 출력되는 것은 없습니다.
참고
이는 PowerShell 함수가 모든 항목이 파이프라인으로 이동되는 출력을 처리하는 방법과 근본적으로 다릅니다.
메서드 출력
이 예제에서는 문을 제외하고 클래스 메서드에서 파이프라인에 대한 우발적인 출력을 return
보여 줍니다.
class FunWithIntegers
{
[int[]]$Integers = 0..10
[int[]]GetOddIntegers(){
return $this.Integers.Where({ ($_ % 2) })
}
[void] GetEvenIntegers(){
# this following line doesn't go to the pipeline
$this.Integers.Where({ ($_ % 2) -eq 0})
}
[string]SayHello(){
# this following line doesn't go to the pipeline
"Good Morning"
# this line goes to the pipeline
return "Hello World"
}
}
$ints = [FunWithIntegers]::new()
$ints.GetOddIntegers()
$ints.GetEvenIntegers()
$ints.SayHello()
1
3
5
7
9
Hello World
생성자
생성자를 사용하면 클래스의 instance 만들 때 기본값을 설정하고 개체 논리의 유효성을 검사할 수 있습니다. 생성자는 클래스와 동일한 이름을 갖습니다. 생성자에는 새 개체의 데이터 멤버를 초기화하는 인수가 있을 수 있습니다.
클래스에는 0개 이상의 생성자가 정의되었을 수 있습니다. 생성자가 정의되지 않은 경우 클래스에는 기본 매개 변수 없는 생성자가 제공됩니다. 이 생성자는 모든 멤버를 기본값으로 초기화합니다. 개체 형식 및 문자열에는 null 값이 지정됩니다. 생성자를 정의할 때 기본 매개 변수가 없는 생성자는 만들어지지 않습니다. 필요한 경우 매개 변수가 없는 생성자를 Create.
생성자 기본 구문
이 예제에서 Device 클래스는 속성 및 생성자로 정의됩니다. 이 클래스를 사용하려면 사용자가 생성자에 나열된 매개 변수에 대한 값을 제공해야 합니다.
class Device {
[string]$Brand
[string]$Model
[string]$VendorSku
Device(
[string]$b,
[string]$m,
[string]$vsk
){
$this.Brand = $b
$this.Model = $m
$this.VendorSku = $vsk
}
}
[Device]$surface = [Device]::new("Microsoft", "Surface Pro 4", "5072641000")
$surface
Brand Model VendorSku
----- ----- ---------
Microsoft Surface Pro 4 5072641000
여러 생성자가 있는 예제
이 예제에서 Device 클래스는 속성, 기본 생성자 및 instance 초기화하는 생성자로 정의됩니다.
기본 생성자는 브랜드를Undefined로 설정하고 모델 및 vendor-sku 를 null 값으로 남깁니다.
class Device {
[string]$Brand
[string]$Model
[string]$VendorSku
Device(){
$this.Brand = 'Undefined'
}
Device(
[string]$b,
[string]$m,
[string]$vsk
){
$this.Brand = $b
$this.Model = $m
$this.VendorSku = $vsk
}
}
[Device]$somedevice = [Device]::new()
[Device]$surface = [Device]::new("Microsoft", "Surface Pro 4", "5072641000")
$somedevice
$surface
Brand Model VendorSku
----- ----- ---------
Undefined
Microsoft Surface Pro 4 5072641000
숨겨진 특성
특성은 hidden
속성 또는 메서드를 덜 표시합니다. 속성 또는 메서드는 사용자가 계속 액세스할 수 있으며 개체를 사용할 수 있는 모든 범위에서 사용할 수 있습니다. 숨겨진 멤버는 cmdlet에서 Get-Member
숨겨져 있으며, 클래스 정의 외부에서 탭 완성 또는 IntelliSense를 사용하여 표시할 수 없습니다.
숨겨진 특성을 사용하는 예제
Rack 개체를 만들 때 디바이스의 슬롯 수는 언제든지 변경해서는 안 되는 고정 값입니다. 이 값은 생성 시 알려져 있습니다.
숨겨진 특성을 사용하면 개발자가 슬롯 수를 숨김 상태로 유지할 수 있으며 의도치 않게 랙 크기가 변경되지 않도록 방지할 수 있습니다.
class Device {
[string]$Brand
[string]$Model
}
class Rack {
[int] hidden $Slots = 8
[string]$Brand
[string]$Model
[Device[]]$Devices = [Device[]]::new($this.Slots)
Rack ([string]$b, [string]$m, [int]$capacity){
## argument validation here
$this.Brand = $b
$this.Model = $m
$this.Slots = $capacity
## reset rack size to new capacity
$this.Devices = [Device[]]::new($this.Slots)
}
}
[Rack]$r1 = [Rack]::new("Microsoft", "Surface Pro 4", 16)
$r1
$r1.Devices.Length
$r1.Slots
Brand Model Devices
----- ----- -------
Microsoft Surface Pro 4 {$null, $null, $null, $null...}
16
16
슬롯 속성 은 출력에 $r1
표시되지 않습니다. 그러나 생성자에 의해 크기가 변경되었습니다.
정적 특성
특성은 static
클래스에 있고 instance 필요 없는 속성 또는 메서드를 정의합니다.
정적 속성은 클래스 인스턴스화와 관계없이 항상 사용할 수 있습니다. 정적 속성은 클래스의 모든 인스턴스에서 공유됩니다. 정적 메서드는 항상 사용할 수 있습니다. 모든 정적 속성은 전체 세션 범위에 대해 라이브로 유지됩니다.
정적 특성 및 메서드를 사용하는 예제
여기에 인스턴스화된 랙이 데이터 센터에 있다고 가정합니다. 따라서 코드의 랙을 추적하려고 합니다.
class Device {
[string]$Brand
[string]$Model
}
class Rack {
hidden [int] $Slots = 8
static [Rack[]]$InstalledRacks = @()
[string]$Brand
[string]$Model
[string]$AssetId
[Device[]]$Devices = [Device[]]::new($this.Slots)
Rack ([string]$b, [string]$m, [string]$id, [int]$capacity){
## argument validation here
$this.Brand = $b
$this.Model = $m
$this.AssetId = $id
$this.Slots = $capacity
## reset rack size to new capacity
$this.Devices = [Device[]]::new($this.Slots)
## add rack to installed racks
[Rack]::InstalledRacks += $this
}
static [void]PowerOffRacks(){
foreach ($rack in [Rack]::InstalledRacks) {
Write-Warning ("Turning off rack: " + ($rack.AssetId))
}
}
}
정적 속성 및 메서드 테스트가 있음
PS> [Rack]::InstalledRacks.Length
0
PS> [Rack]::PowerOffRacks()
PS> (1..10) | ForEach-Object {
>> [Rack]::new("Adatum Corporation", "Standard-16",
>> $_.ToString("Std0000"), 16)
>> } > $null
PS> [Rack]::InstalledRacks.Length
10
PS> [Rack]::InstalledRacks[3]
Brand Model AssetId Devices
----- ----- ------- -------
Adatum Corporation Standard-16 Std0004 {$null, $null, $null, $null...}
PS> [Rack]::PowerOffRacks()
WARNING: Turning off rack: Std0001
WARNING: Turning off rack: Std0002
WARNING: Turning off rack: Std0003
WARNING: Turning off rack: Std0004
WARNING: Turning off rack: Std0005
WARNING: Turning off rack: Std0006
WARNING: Turning off rack: Std0007
WARNING: Turning off rack: Std0008
WARNING: Turning off rack: Std0009
WARNING: Turning off rack: Std0010
이 예제를 실행할 때마다 랙 수가 증가합니다.
속성 유효성 검사 특성
유효성 검사 특성을 사용하면 속성에 지정된 값이 정의된 요구 사항을 충족하는지 테스트할 수 있습니다. 값이 할당되는 순간 유효성 검사가 트리거됩니다. about_functions_advanced_parameters 참조하세요.
유효성 검사 특성을 사용하는 예제
class Device {
[ValidateNotNullOrEmpty()][string]$Brand
[ValidateNotNullOrEmpty()][string]$Model
}
[Device]$dev = [Device]::new()
Write-Output "Testing dev"
$dev
$dev.Brand = ""
Testing dev
Brand Model
----- -----
Exception setting "Brand": "The argument is null or empty. Provide an
argument that is not null or empty, and then try the command again."
At C:\tmp\Untitled-5.ps1:11 char:1
+ $dev.Brand = ""
+ ~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], SetValueInvocationException
+ FullyQualifiedErrorId : ExceptionWhenSetting
PowerShell 클래스의 상속
기존 클래스에서 파생되는 새 클래스를 만들어 클래스를 확장할 수 있습니다. 파생 클래스는 기본 클래스의 속성을 상속합니다. 필요에 따라 메서드 및 속성을 추가하거나 재정의할 수 있습니다.
PowerShell은 여러 상속을 지원하지 않습니다. 클래스는 둘 이상의 클래스에서 상속할 수 없습니다. 그러나 해당 용도로 인터페이스를 사용할 수 있습니다.
상속 구현은 연산자에 :
의해 정의됩니다. 즉, 이 클래스를 확장하거나 이러한 인터페이스를 구현합니다. 파생 클래스는 항상 클래스 선언에서 맨 왼쪽에 있어야 합니다.
단순 상속 구문을 사용하는 예제
이 예제에서는 간단한 PowerShell 클래스 상속 구문을 보여줍니다.
Class Derived : Base {...}
이 예제에서는 기본 클래스 다음에 오는 인터페이스 선언이 있는 상속을 보여 있습니다.
Class Derived : Base.Interface {...}
PowerShell 클래스의 단순 상속 예제
이 예제에서는 이전 예제에서 사용된 Rack 및 Device 클래스를 더 잘 정의하여 속성 반복을 방지하고, 공통 속성을 더 잘 정렬하고, 일반적인 비즈니스 논리를 다시 사용합니다.
데이터 센터의 대부분의 개체는 회사 자산이며, 이를 자산으로 추적하기 시작하는 것이 좋습니다. 디바이스 유형은 열거형에 DeviceType
의해 정의됩니다. 열거형에 대한 자세한 내용은 about_Enum 참조하세요.
이 예제에서는 및 ComputeServer
만 정의합니다Rack
. 두 확장 모두 클래스입니다Device
.
enum DeviceType {
Undefined = 0
Compute = 1
Storage = 2
Networking = 4
Communications = 8
Power = 16
Rack = 32
}
class Asset {
[string]$Brand
[string]$Model
}
class Device : Asset {
hidden [DeviceType]$devtype = [DeviceType]::Undefined
[string]$Status
[DeviceType] GetDeviceType(){
return $this.devtype
}
}
class ComputeServer : Device {
hidden [DeviceType]$devtype = [DeviceType]::Compute
[string]$ProcessorIdentifier
[string]$Hostname
}
class Rack : Device {
hidden [DeviceType]$devtype = [DeviceType]::Rack
hidden [int]$Slots = 8
[string]$Datacenter
[string]$Location
[Device[]]$Devices = [Device[]]::new($this.Slots)
Rack (){
## Just create the default rack with 8 slots
}
Rack ([int]$s){
## Add argument validation logic here
$this.Devices = [Device[]]::new($s)
}
[void] AddDevice([Device]$dev, [int]$slot){
## Add argument validation logic here
$this.Devices[$slot] = $dev
}
[void] RemoveDevice([int]$slot){
## Add argument validation logic here
$this.Devices[$slot] = $null
}
}
$FirstRack = [Rack]::new(16)
$FirstRack.Status = "Operational"
$FirstRack.Datacenter = "PNW"
$FirstRack.Location = "F03R02.J10"
(0..15).ForEach({
$ComputeServer = [ComputeServer]::new()
$ComputeServer.Brand = "Fabrikam, Inc." ## Inherited from Asset
$ComputeServer.Model = "Fbk5040" ## Inherited from Asset
$ComputeServer.Status = "Installed" ## Inherited from Device
$ComputeServer.ProcessorIdentifier = "x64" ## ComputeServer
$ComputeServer.Hostname = ("r1s" + $_.ToString("000")) ## ComputeServer
$FirstRack.AddDevice($ComputeServer, $_)
})
$FirstRack
$FirstRack.Devices
Datacenter : PNW
Location : F03R02.J10
Devices : {r1s000, r1s001, r1s002, r1s003...}
Status : Operational
Brand :
Model :
ProcessorIdentifier : x64
Hostname : r1s000
Status : Installed
Brand : Fabrikam, Inc.
Model : Fbk5040
ProcessorIdentifier : x64
Hostname : r1s001
Status : Installed
Brand : Fabrikam, Inc.
Model : Fbk5040
<... content truncated here for brevity ...>
ProcessorIdentifier : x64
Hostname : r1s015
Status : Installed
Brand : Fabrikam, Inc.
Model : Fbk5040
기본 클래스 생성자 호출
하위 클래스에서 기본 클래스 생성자를 호출하려면 키워드(keyword) 추가 base
합니다.
class Person {
[int]$Age
Person([int]$a)
{
$this.Age = $a
}
}
class Child : Person
{
[string]$School
Child([int]$a, [string]$s ) : base($a) {
$this.School = $s
}
}
[Child]$littleone = [Child]::new(10, "Silver Fir Elementary School")
$littleone.Age
10
기본 클래스 메서드 호출
서브클래스의 기존 메서드를 재정의하려면 동일한 이름과 서명을 사용하여 메서드를 선언합니다.
class BaseClass
{
[int]days() {return 1}
}
class ChildClass1 : BaseClass
{
[int]days () {return 2}
}
[ChildClass1]::new().days()
2
재정의된 구현에서 기본 클래스 메서드를 호출하려면 호출 시 기본 클래스([baseclass]$this)로 캐스팅합니다.
class BaseClass
{
[int]days() {return 1}
}
class ChildClass1 : BaseClass
{
[int]days () {return 2}
[int]basedays() {return ([BaseClass]$this).days()}
}
[ChildClass1]::new().days()
[ChildClass1]::new().basedays()
2
1
인터페이스
인터페이스를 선언하는 구문은 C#과 유사합니다. 기본 형식이 지정되지 않은 경우 기본 형식 뒤 또는 콜론(:
) 바로 다음에 인터페이스를 선언할 수 있습니다. 모든 형식 이름을 쉼표로 구분합니다.
class MyComparable : system.IComparable
{
[int] CompareTo([object] $obj)
{
return 0;
}
}
class MyComparableBar : bar, system.IComparable
{
[int] CompareTo([object] $obj)
{
return 0;
}
}
PowerShell 모듈에서 클래스 가져오기
Import-Module
문은 #requires
모듈에서 정의한 대로 모듈 함수, 별칭 및 변수만 가져옵니다. 클래스를 가져오지 않습니다. 문은 using module
모듈에 정의된 클래스를 가져옵니다. 모듈이 현재 세션 using
에 로드되지 않으면 문이 실패합니다.