about_Classes_Constructors
Korte beschrijving
Hierin wordt beschreven hoe u constructors voor PowerShell-klassen definieert.
Lange beschrijving
Met constructors kunt u standaardwaarden instellen en objectlogica valideren op het moment dat het exemplaar van de klasse wordt gemaakt. Constructors hebben dezelfde naam als de klasse. Constructors kunnen parameters hebben om de gegevensleden van het nieuwe object te initialiseren.
PowerShell-klasseconstructors worden gedefinieerd als speciale methoden voor de klasse. Ze gedragen zich hetzelfde als PowerShell-klassemethoden, met de volgende uitzonderingen:
- Constructors hebben geen uitvoertype. Ze kunnen het
return
trefwoord niet gebruiken. - Constructors hebben altijd dezelfde naam als de klasse.
- Constructors kunnen niet rechtstreeks worden aangeroepen. Ze worden alleen uitgevoerd wanneer een exemplaar wordt gemaakt.
- Constructors worden nooit weergegeven in de uitvoer voor de
Get-Member
cmdlet.
Zie about_Classes_Methods voor meer informatie over PowerShell-klassenmethoden.
Voor de klasse kunnen nul of meer constructors zijn gedefinieerd. Als er geen constructor is gedefinieerd, krijgt de klasse een standaardconstructor zonder parameter. Deze constructor initialiseert alle leden naar hun standaardwaarden. Objecttypen en tekenreeksen krijgen null-waarden. Wanneer u de constructor definieert, wordt er geen standaardconstructor zonder parameter gemaakt. Creatie indien nodig een constructor zonder parameters.
U kunt ook een statische constructor zonder parameters definiëren.
Syntax
Klasseconstructors gebruiken de volgende syntaxis:
Standaardconstructorsyntaxis
<class-name> () [: base([<params>])] {
<body>
}
Statische constructorsyntaxis
static <class-name> () [: base([<params>])] {
<body>
}
Geparameteriseerde constructorsyntaxis (één regel)
<class-name> ([[<parameter-type>]$<parameter-name>[, [<parameter-type>]$<parameter-name>...]]) [: base([<params>])] {
<body>
}
Geparameteriseerde constructorsyntaxis (meerdere regels)
<class-name> (
[<parameter-type>]$<parameter-name>[,
[<parameter-type>]$<parameter-name>...]
) [: base([<params>])] {
<body>
}
Voorbeelden
Voorbeeld 1: een klasse definiëren met de standaardconstructor
De klasse ExampleBook1 definieert geen constructor. In plaats daarvan wordt de automatische standaardconstructor gebruikt.
class ExampleBook1 {
[string] $Name
[string] $Author
[int] $Pages
[datetime] $PublishedOn
}
[ExampleBook1]::new()
Name Author Pages PublishedOn
---- ------ ----- -----------
0 1/1/0001 12:00:00 AM
Notitie
De standaardwaarde voor de eigenschappen Naam en Auteur is $null
omdat ze zijn getypt als tekenreeksen. Dit is een verwijzingstype. De andere eigenschappen hebben de standaardwaarde voor het gedefinieerde type, omdat het eigenschappen van het waardetype zijn. Zie 'Standaardeigenschapswaarden' in about_Classes_Properties voor meer informatie over de standaardwaarden voor eigenschappen.
Voorbeeld 2: de standaardconstructor overschrijven
ExampleBook2 definieert expliciet de standaardconstructor, waarbij de waarden voor PublishedOn worden ingesteld op de huidige datum en Pagina's op 1
.
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
Voorbeeld 3: overbelasting van constructor definiëren
De klasse ExampleBook3 definieert drie constructor-overloads, waardoor gebruikers een exemplaar van de klasse kunnen maken op basis van een hashtabel, door elke eigenschapswaarde door te geven en door de naam van het boek en de auteur door te geven. De klasse definieert de standaardconstructor niet.
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".
Als u de standaardconstructor aanroept, wordt een methode-uitzondering geretourneerd. De automatische standaardconstructor wordt alleen gedefinieerd voor een klasse wanneer de klasse geen constructors definieert. Omdat ExampleBook3 meerdere overloads definieert, wordt de standaardconstructor niet automatisch toegevoegd aan de klasse.
Voorbeeld 4: constructors koppelen met een gedeelde methode
In dit voorbeeld ziet u hoe u herbruikbare gedeelde code voor constructors kunt schrijven.
PowerShell-klassen kunnen geen gebruik maken van constructorkoppeling, dus in deze voorbeeldklasse wordt in plaats daarvan een Init()
methode gedefinieerd. De methode heeft verschillende overbelastingen. De overloads met minder parameters roepen de meer expliciete overloads aan met standaardwaarden voor de niet-opgegeven parameters.
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
Voorbeeld 5: Afgeleide klasseconstructors
In de volgende voorbeelden worden klassen gebruikt die de statische, standaardconstructors en geparameteriseerde constructors definiëren voor een basisklasse en een afgeleide klasse die wordt overgenomen van de basisklasse.
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)
}
}
In het volgende blok ziet u de uitgebreide berichten voor het aanroepen van de basisklasseconstructors. Het statische constructorbericht wordt alleen verzonden wanneer er voor het eerst een exemplaar van de klasse wordt gemaakt.
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)
In het volgende blok ziet u de uitgebreide berichten voor het aanroepen van de afgeleide klasseconstructors in een nieuwe sessie. De eerste keer dat een afgeleide klasseconstructor wordt aangeroepen, worden de statische constructors voor de basisklasse en afgeleide klasse aangeroepen. Deze constructors worden niet opnieuw aangeroepen in de sessie. De constructors voor de basisklasse worden altijd uitgevoerd vóór de constructors voor de afgeleide klasse.
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)
Volgorde van uitvoering van constructor
Wanneer een klasse een instantie maakt, wordt de code voor een of meer constructors uitgevoerd.
Voor klassen die niet overnemen van een andere klasse, is de volgorde:
- De statische constructor voor de klasse.
- De toepasselijke constructoroverbelasting voor de klasse.
Voor afgeleide klassen die overnemen van een andere klasse, is de volgorde:
- De statische constructor voor de basisklasse.
- De statische constructor voor de afgeleide klasse.
- Als de afgeleide klasseconstructor expliciet een overbelasting van de basisconstructor aanroept, wordt die constructor uitgevoerd voor de basisklasse. Als er niet expliciet een basisconstructor wordt aangeroepen, wordt de standaardconstructor voor de basisklasse uitgevoerd.
- De toepasselijke constructoroverbelasting voor de afgeleide klasse.
In alle gevallen worden statische constructors slechts eenmaal in een sessie uitgevoerd.
Zie voorbeeld 5 voor een voorbeeld van het gedrag en de volgorde van de constructor.
Verborgen constructors
U kunt constructors van een klasse verbergen door deze te declareren met het hidden
trefwoord. Verborgen klasseconstructors zijn:
- Niet opgenomen in de standaarduitvoer voor de klasse.
- Niet opgenomen in de lijst met klasseleden die door de
Get-Member
cmdlet worden geretourneerd. Als u verborgen eigenschappen wilt weergeven metGet-Member
, gebruikt u de parameter Force . - Wordt niet weergegeven in tabvoltooiing of IntelliSense, tenzij de voltooiing plaatsvindt in de klasse die de verborgen eigenschap definieert.
- Openbare leden van de klasse. Ze kunnen worden geopend en gewijzigd. Als u een eigenschap verbergt, wordt deze niet privé. Alleen de eigenschap wordt verborgen zoals beschreven in de vorige punten.
Notitie
Wanneer u een constructor verbergt, wordt de new()
optie verwijderd uit IntelliSense en voltooiingsresultaten.
Zie about_Hidden voor meer informatie over het hidden
trefwoord.
Statische constructors
U kunt een constructor definiëren als behorend tot de klasse zelf in plaats van exemplaren van de klasse door de constructor te declareren met het static
trefwoord.
Statische klasseconstructors:
- Roep alleen de eerste keer aan dat een exemplaar van de klasse wordt gemaakt in de sessie.
- Kan geen parameters hebben.
- Kan geen toegang krijgen tot exemplaareigenschappen of -methoden met de
$this
variabele.
Constructors voor afgeleide klassen
Wanneer een klasse wordt overgenomen van een andere klasse, kunnen constructors een constructor van de basisklasse aanroepen met het base
trefwoord. Als de afgeleide klasse niet expliciet een constructor aanroept van de basisklasse, wordt in plaats daarvan de standaardconstructor voor de basisklasse aangeroepen.
Als u een niet-standaardbasisconstructor wilt aanroepen, voegt u toe : base(<parameters>)
na de constructorparameters en vóór het hoofdtekstblok.
class <derived-class> : <base-class> {
<derived-class>(<derived-parameters>) : <base-class>(<base-parameters>) {
# initialization code
}
}
Bij het definiëren van een constructor die een basisklasseconstructor aanroept, kunnen de parameters een van de volgende items zijn:
- De variabele van een parameter op de afgeleide klasseconstructor.
- Een statische waarde.
- Een expressie die resulteert in een waarde van het parametertype.
Zie voorbeeld 5 voor een voorbeeld van constructors op een afgeleide klasse.
Ketenconstructors
In tegenstelling tot C# kunnen PowerShell-klasseconstructors geen gebruik maken van ketens met de : this(<parameters>)
syntaxis. Als u codeduplicatie wilt verminderen, gebruikt u een verborgen Init()
methode met meerdere overbelastingen met hetzelfde effect. In voorbeeld 4 ziet u een klasse met dit patroon.
Exemplaareigenschappen en -methoden toevoegen met Update-TypeData
Naast het rechtstreeks declareren van eigenschappen en methoden in de klassedefinitie, kunt u eigenschappen definiëren voor exemplaren van een klasse in de statische constructor met behulp van de Update-TypeData
cmdlet.
Gebruik dit codefragment als beginpunt voor het patroon. Vervang indien nodig de tekst van de tijdelijke aanduiding tussen punthaken.
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
}
}
}
Tip
De Add-Member
cmdlet kan eigenschappen en methoden toevoegen aan een klasse in niet-statische constructors, maar de cmdlet wordt elke keer uitgevoerd wanneer de constructor wordt aangeroepen. Als Update-TypeData
u in de statische constructor gebruikt, zorgt u ervoor dat de code voor het toevoegen van de leden aan de klasse slechts eenmaal in een sessie hoeft te worden uitgevoerd.
Voeg alleen eigenschappen toe aan de klasse in niet-statische constructors wanneer deze niet kunnen worden gedefinieerd met Update-TypeData
, zoals alleen-lezeneigenschappen.
Zie about_Classes_Methods voor meer informatie over het definiëren van exemplaarmethoden metUpdate-TypeData
. Zie about_Classes_Properties voor meer informatie over het definiëren van exemplaareigenschappen metUpdate-TypeData
.
Beperkingen
PowerShell-klasseconstructors hebben de volgende beperkingen:
Constructorkoppeling is niet geïmplementeerd.
Tijdelijke oplossing: definieer verborgen
Init()
methoden en roep deze aan vanuit de constructors.Constructorparameters kunnen geen kenmerken gebruiken, inclusief validatiekenmerken.
Tijdelijke oplossing: wijs de parameters in de constructorbody opnieuw toe met het validatiekenmerk.
Constructorparameters kunnen geen standaardwaarden definiëren. De parameters zijn altijd verplicht.
Tijdelijke oplossing: geen.
Als een overbelasting van een constructor verborgen is, wordt elke overbelasting voor de constructor ook als verborgen behandeld.
Tijdelijke oplossing: geen.