about_Classes_Constructors
Krátký popis
Popisuje, jak definovat konstruktory pro třídy PowerShellu.
Dlouhý popis
Konstruktory umožňují nastavit výchozí hodnoty a ověřit logiku objektu v okamžiku vytvoření instance třídy. Konstruktory mají stejný název jako třída. Konstruktory mohou mít parametry pro inicializaci datových členů nového objektu.
Konstruktory třídy PowerShellu jsou definovány jako speciální metody třídy. Chovají se stejně jako metody třídy PowerShellu s následujícími výjimkami:
- Konstruktory nemají výstupní typ. Klíčové slovo nemůžou
return
použít. - Konstruktory mají vždy stejný název jako třída.
- Konstruktory nelze volat přímo. Spustí se pouze při vytvoření instance.
- Konstruktory se ve výstupu rutiny
Get-Member
nikdy nezobrazí.
Další informace o metodách třídy PowerShellu najdete v tématu about_Classes_Methods.
Třída může mít definované nula nebo více konstruktorů. Pokud není definován žádný konstruktor, třída má výchozí konstruktor bez parametrů. Tento konstruktor inicializuje všechny členy na jejich výchozí hodnoty. Typy objektů a řetězce mají hodnoty null. Při definování konstruktoru se nevytvořil žádný výchozí konstruktor bez parametrů. Pokud je potřeba, vytvořte konstruktor bez parametrů.
Můžete také definovat statický konstruktor bez parametrů.
Syntaxe
Konstruktory tříd používají následující syntaxe:
Výchozí syntaxe konstruktoru
<class-name> () [: base([<params>])] {
<body>
}
Syntaxe statického konstruktoru
static <class-name> () [: base([<params>])] {
<body>
}
Syntaxe parametrizovaného konstruktoru (jeden řádek)
<class-name> ([[<parameter-type>]$<parameter-name>[, [<parameter-type>]$<parameter-name>...]]) [: base([<params>])] {
<body>
}
Syntaxe parametrizovaného konstruktoru (víceřádkové)
<class-name> (
[<parameter-type>]$<parameter-name>[,
[<parameter-type>]$<parameter-name>...]
) [: base([<params>])] {
<body>
}
Příklady
Příklad 1 – Definování třídy s výchozím konstruktorem
Třída ExampleBook1 nedefinuje konstruktor. Místo toho používá automatický výchozí konstruktor.
class ExampleBook1 {
[string] $Name
[string] $Author
[int] $Pages
[datetime] $PublishedOn
}
[ExampleBook1]::new()
Name Author Pages PublishedOn
---- ------ ----- -----------
0 1/1/0001 12:00:00 AM
Poznámka:
Výchozí hodnota vlastností Name a Author je $null
, protože jsou zadány jako řetězce, což je typ odkazu. Ostatní vlastnosti mají výchozí hodnotu pro jejich definovaný typ, protože se jedná o vlastnosti typu hodnoty. Další informace o výchozích hodnotách vlastností najdete v tématu Výchozí hodnoty vlastností v about_Classes_Properties.
Příklad 2 – Přepsání výchozího konstruktoru
ExampleBook2 explicitně definuje výchozí konstruktor a nastaví hodnoty PublishedOn na aktuální datum a Pages na 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
Příklad 3 – Definování přetížení konstruktoru
Třída ExampleBook3 definuje tři přetížení konstruktoru, což uživatelům umožňuje vytvořit instanci třídy z hashtable, předáním každé hodnoty vlastnosti a předáním názvu knihy a autora. Třída nedefinuje výchozí konstruktor.
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".
Volání výchozího konstruktoru vrátí výjimku metody. Automatický výchozí konstruktor je definován pouze pro třídu, pokud třída nedefinuje žádné konstruktory. Protože ExampleBook3 definuje více přetížení, výchozí konstruktor není automaticky přidán do třídy.
Příklad 4 – řetězení konstruktorů se sdílenou metodou
Tento příklad ukazuje, jak můžete pro konstruktory psát opakovaně použitelný sdílený kód.
Třídy PowerShellu nemůžou používat řetězení konstruktorů, takže tato ukázková třída místo toho definuje metodu Init()
. Metoda má několik přetížení. Přetížení s menším počtem parametrů volají explicitnější přetížení s výchozími hodnotami pro nespecifikované parametry.
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
Příklad 5 – konstruktory odvozené třídy
Následující příklady používají třídy, které definují statické, výchozí a parametrizované konstruktory pro základní třídu a odvozenou třídu, která dědí ze základní třídy.
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)
}
}
Následující blok ukazuje podrobné zasílání zpráv pro volání konstruktorů základní třídy. Zpráva statického konstruktoru se vygeneruje pouze při prvním vytvoření instance třídy.
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)
Další blok ukazuje podrobné zasílání zpráv pro volání konstruktorů odvozené třídy v nové relaci. Při prvním zavolání konstruktoru odvozené třídy se volají statické konstruktory základní třídy a odvozené třídy. Tyto konstruktory se v relaci znovu nevolají. Konstruktory základní třídy vždy běží před konstruktory pro odvozenou třídu.
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)
Řazení spuštění konstruktoru
Při vytvoření instance třídy se spustí kód jednoho nebo více konstruktorů.
U tříd, které nedědí z jiné třídy, je řazení následující:
- Statický konstruktor pro třídu.
- Příslušné přetížení konstruktoru pro třídu.
Pro odvozené třídy, které dědí z jiné třídy, řazení je:
- Statický konstruktor základní třídy.
- Statický konstruktor pro odvozenou třídu.
- Pokud konstruktor odvozené třídy explicitně volá přetížení základního konstruktoru, spustí tento konstruktor pro základní třídu. Pokud nevolá explicitně základní konstruktor, spustí výchozí konstruktor základní třídy.
- Příslušné přetížení konstruktoru pro odvozenou třídu.
Ve všech případech se statické konstruktory spouští pouze jednou v relaci.
Příklad chování a řazení konstruktoru naleznete v příkladu 5.
Skryté konstruktory
Konstruktory třídy můžete skrýt deklarováním pomocí klíčového hidden
slova. Skryté konstruktory tříd jsou:
- Nezahrnut do výchozího výstupu pro třídu.
- Součástí seznamu členů třídy vrácených rutinou
Get-Member
není. Pokud chcete zobrazit skryté vlastnosti pomocíGet-Member
parametru Force . - Nezobrazuje se v dokončování tabulátoru nebo IntelliSense, pokud nedojde k dokončení ve třídě, která definuje skrytou vlastnost.
- Veřejné členy třídy. K nim je možné přistupovat a upravovat. Skrytí vlastnosti ho neudělá jako soukromou. Skryje vlastnost, jak je popsáno v předchozích bodech.
Poznámka:
Když skryjete jakýkoli konstruktor, new()
možnost se odebere z IntelliSense a výsledků dokončení.
Další informace o klíčovém slově hidden
najdete v tématu about_Hidden.
Statické konstruktory
Konstruktor můžete definovat jako patřící do samotné třídy místo instancí třídy deklarací konstruktoru s klíčovým slovem static
.
Statické konstruktory tříd:
- Vyvolání pouze při prvním vytvoření instance třídy v relaci.
- Nemůže mít žádné parametry.
- Nelze získat přístup k vlastnostem instance nebo metodám s proměnnou
$this
.
Konstruktory pro odvozené třídy
Když třída dědí z jiné třídy, konstruktory mohou vyvolat konstruktor ze základní třídy s klíčovým slovem base
. Pokud odvozená třída explicitně nevyvolá konstruktor ze základní třídy, vyvolá místo toho výchozí konstruktor základní třídy.
Chcete-li vyvolat nedefault základní konstruktor, přidejte : base(<parameters>)
za parametry konstruktoru a před blok těla.
class <derived-class> : <base-class> {
<derived-class>(<derived-parameters>) : <base-class>(<base-parameters>) {
# initialization code
}
}
Při definování konstruktoru, který volá konstruktor základní třídy, mohou být parametry některé z následujících položek:
- Proměnná libovolného parametru v konstruktoru odvozené třídy.
- Libovolná statická hodnota.
- Libovolný výraz, který se vyhodnotí jako hodnota typu parametru.
Příklad konstruktorů v odvozené třídě naleznete v příkladu 5.
Řetězení konstruktorů
Na rozdíl od jazyka C# nemůžou konstruktory tříd PowerShellu : this(<parameters>)
používat řetězení se syntaxí. Chcete-li omezit duplikaci kódu, použijte skrytou Init()
metodu s více přetíženími na stejný účinek. Příklad 4 ukazuje třídu používající tento vzor.
Přidání vlastností a metod instance pomocí Update-TypeData
Kromě deklarování vlastností a metod přímo v definici třídy můžete definovat vlastnosti pro instance třídy ve statickém konstruktoru pomocí rutiny Update-TypeData
.
Tento fragment kódu použijte jako výchozí bod pro vzor. Podle potřeby nahraďte zástupný text v úhlových závorkách.
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
Rutina Add-Member
může přidat vlastnosti a metody do třídy v nestatického konstruktoru, ale rutina se spustí při každém zavolání konstruktoru. Použití Update-TypeData
ve statickém konstruktoru zajišťuje, že kód pro přidání členů do třídy musí běžet pouze jednou v relaci.
Pouze přidat vlastnosti do třídy v nestatické konstruktory, pokud nelze definovat pomocí Update-TypeData
, jako jsou vlastnosti jen pro čtení.
Další informace o definování metod instance pomocí Update-TypeData
naleznete v tématu about_Classes_Methods. Další informace o definování vlastností instance pomocí Update-TypeData
naleznete v tématu about_Classes_Properties.
Omezení
Konstruktory tříd PowerShellu mají následující omezení:
Řetězení konstruktorů není implementováno.
Alternativní řešení: Definujte skryté
Init()
metody a volejte je z konstruktorů.Parametry konstruktoru nemohou používat žádné atributy, včetně ověřovacích atributů.
Alternativní řešení: Přeřaďte parametry v těle konstruktoru pomocí ověřovacího atributu.
Parametry konstruktoru nemůžou definovat výchozí hodnoty. Parametry jsou vždy povinné.
Řešení: Žádné.
Pokud je jakékoli přetížení konstruktoru skryté, je každé přetížení konstruktoru považováno za skryté.
Řešení: Žádné.
Viz také
Váš názor
https://aka.ms/ContentUserFeedback.
Připravujeme: V průběhu roku 2024 budeme postupně vyřazovat problémy z GitHub coby mechanismus zpětné vazby pro obsah a nahrazovat ho novým systémem zpětné vazby. Další informace naleznete v tématu:Odeslat a zobrazit názory pro