Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Krátký popis
Popisuje, jak můžete definovat třídy, které rozšiřují další typy.
Dlouhý popis
Třídy PowerShellu podporují dědičnost, což umožňuje definovat podřízenou třídu, která znovu používá (dědí), rozšiřuje nebo upravuje chování nadřazené třídy. Třída, jejíž členy jsou zděděné, se nazývá základní třída. Třída, která dědí členy základní třídy, se nazývá odvozená třída.
PowerShell podporuje pouze jednu dědičnost. Třída může dědit pouze z jedné třídy. Dědičnost je však tranzitivní, což umožňuje definovat hierarchii dědičnosti pro sadu typů. Jinými slovy, typ D může dědit z typu C, který dědí z typu B, který dědí ze základního typu třídy . Vzhledem k tomu, že dědičnost je přechodná, jsou členy typu A k dispozici pro typ D.
Odvozené třídy nedědí všechny členy základní třídy. Následující členové nejsou zděděni:
- Statické konstruktory, které inicializují statická data třídy.
- Konstruktory instance, které voláte k vytvoření nové instance třídy. Každá třída musí definovat vlastní konstruktory.
Třídu můžete rozšířit vytvořením nové třídy, která je odvozena z existující třídy. Odvozená třída dědí vlastnosti a metody základní třídy. Podle potřeby můžete přidat nebo přepsat členy základní třídy.
Třídy mohou také dědit z rozhraní, která definují kontrakt. Třída, která dědí z rozhraní, musí implementovat tento kontrakt. Pokud ano, třída je použitelná jako jakákoli jiná třída implementovaná v daném rozhraní. Pokud třída dědí z rozhraní, ale neimplementuje rozhraní, PowerShell vyvolá chybu analýzy třídy.
Některé operátory PowerShellu závisí na třídě, která implementuje konkrétní rozhraní.
Například operátor -eq kontroluje pouze rovnost odkazů, pokud třída neimplementuje System.IEquatable rozhraní. Operátory -le, -lt, -gea -gt pracují pouze na třídách, které implementují rozhraní System.IComparable.
Odvozená třída používá syntaxi : k rozšíření základní třídy nebo implementaci rozhraní. Odvozená třída by měla být vždy ponechána nejvíce v deklaraci třídy.
Tento příklad ukazuje základní syntaxi dědičnosti tříd PowerShellu.
class Derived : Base {...}
Tento příklad ukazuje dědičnost s deklarací rozhraní přicházející po základní třídě.
class Derived : Base, Interface {...}
Syntaxe
Dědičnost tříd používá následující syntaxe:
Syntaxe jednoho řádku
class <derived-class-name> : <base-class-or-interface-name>[, <interface-name>...] {
<derived-class-body>
}
Například:
# Base class only
class Derived : Base {...}
# Interface only
class Derived : System.IComparable {...}
# Base class and interface
class Derived : Base, System.IComparable {...}
Víceřádkové syntaxe
class <derived-class-name> : <base-class-or-interface-name>[,
<interface-name>...] {
<derived-class-body>
}
Například:
class Derived : Base,
System.IComparable,
System.IFormattable,
System.IConvertible {
# Derived class definition
}
Examples
Příklad 1 – Dědění a přepsání ze základní třídy
Následující příklad ukazuje chování zděděných vlastností s a bez přepsání. Po přečtení popisu spusťte bloky kódu v pořadí.
Definování základní třídy
První blok kódu definuje PublishedWork jako základní třídu. Má dvě statické vlastnosti, Seznam a Artists. Dále definuje statickou metodu RegisterWork(), která se má přidat do statického List vlastnost a interprety do vlastnosti Artists a zapsat zprávu pro každou novou položku v seznamech.
Třída definuje tři vlastnosti instance, které popisují publikovanou práci.
Nakonec definuje Register() a ToString() metody instance.
class PublishedWork {
static [PublishedWork[]] $List = @()
static [string[]] $Artists = @()
static [void] RegisterWork([PublishedWork]$Work) {
$wName = $Work.Name
$wArtist = $Work.Artist
if ($Work -notin [PublishedWork]::List) {
Write-Verbose "Adding work '$wName' to works list"
[PublishedWork]::List += $Work
} else {
Write-Verbose "Work '$wName' already registered."
}
if ($wArtist -notin [PublishedWork]::Artists) {
Write-Verbose "Adding artist '$wArtist' to artists list"
[PublishedWork]::Artists += $wArtist
} else {
Write-Verbose "Artist '$wArtist' already registered."
}
}
static [void] ClearRegistry() {
Write-Verbose "Clearing PublishedWork registry"
[PublishedWork]::List = @()
[PublishedWork]::Artists = @()
}
[string] $Name
[string] $Artist
[string] $Category
[void] Init([string]$WorkType) {
if ([string]::IsNullOrEmpty($this.Category)) {
$this.Category = "${WorkType}s"
}
}
PublishedWork() {
$WorkType = $this.GetType().FullName
$this.Init($WorkType)
Write-Verbose "Defined a published work of type [$WorkType]"
}
PublishedWork([string]$Name, [string]$Artist) {
$WorkType = $this.GetType().FullName
$this.Name = $Name
$this.Artist = $Artist
$this.Init($WorkType)
Write-Verbose "Defined '$Name' by $Artist as a published work of type [$WorkType]"
}
PublishedWork([string]$Name, [string]$Artist, [string]$Category) {
$WorkType = $this.GetType().FullName
$this.Name = $Name
$this.Artist = $Artist
$this.Init($WorkType)
Write-Verbose "Defined '$Name' by $Artist ($Category) as a published work of type [$WorkType]"
}
[void] Register() { [PublishedWork]::RegisterWork($this) }
[string] ToString() { return "$($this.Name) by $($this.Artist)" }
}
Definování odvozené třídy bez přepsání
První odvozená třída je Album. Nepřepíše žádné vlastnosti ani metody. Přidá novou vlastnost instance, Žánry, která neexistuje v základní třídě.
class Album : PublishedWork {
[string[]] $Genres = @()
}
Následující blok kódu ukazuje chování odvozené Album třídy.
Nejprve nastaví $VerbosePreference tak, aby zprávy z metod třídy vysílaly do konzoly. Vytvoří tři instance třídy, zobrazí je v tabulce a pak je zaregistruje pomocí zděděné statické RegisterWork() metody. Potom volá stejnou statickou metodu přímo v základní třídě.
$VerbosePreference = 'Continue'
$Albums = @(
[Album]@{
Name = 'The Dark Side of the Moon'
Artist = 'Pink Floyd'
Genres = 'Progressive rock', 'Psychedelic rock'
}
[Album]@{
Name = 'The Wall'
Artist = 'Pink Floyd'
Genres = 'Progressive rock', 'Art rock'
}
[Album]@{
Name = '36 Chambers'
Artist = 'Wu-Tang Clan'
Genres = 'Hip hop'
}
)
$Albums | Format-Table
$Albums | ForEach-Object { [Album]::RegisterWork($_) }
$Albums | ForEach-Object { [PublishedWork]::RegisterWork($_) }
VERBOSE: Defined a published work of type [Album]
VERBOSE: Defined a published work of type [Album]
VERBOSE: Defined a published work of type [Album]
Genres Name Artist Category
------ ---- ------ --------
{Progressive rock, Psychedelic rock} The Dark Side of the Moon Pink Floyd Albums
{Progressive rock, Art rock} The Wall Pink Floyd Albums
{Hip hop} 36 Chambers Wu-Tang Clan Albums
VERBOSE: Adding work 'The Dark Side of the Moon' to works list
VERBOSE: Adding artist 'Pink Floyd' to artists list
VERBOSE: Adding work 'The Wall' to works list
VERBOSE: Artist 'Pink Floyd' already registered.
VERBOSE: Adding work '36 Chambers' to works list
VERBOSE: Adding artist 'Wu-Tang Clan' to artists list
VERBOSE: Work 'The Dark Side of the Moon' already registered.
VERBOSE: Artist 'Pink Floyd' already registered.
VERBOSE: Work 'The Wall' already registered.
VERBOSE: Artist 'Pink Floyd' already registered.
VERBOSE: Work '36 Chambers' already registered.
VERBOSE: Artist 'Wu-Tang Clan' already registered.
Všimněte si, že i když Album třída nedefinovala hodnotu pro Category nebo jakékoli konstruktory, byla vlastnost definována výchozím konstruktorem základní třídy.
Ve podrobném zasílání zpráv druhé volání metody RegisterWork() hlásí, že díla a umělci jsou již zaregistrováni. I když první volání RegisterWork() bylo pro odvozenou třídu Album, použila zděděnou statickou metodu ze základní PublishedWork třídy. Tato metoda aktualizovala statické List a Artist vlastnosti základní třídy, kterou odvozená třída nepřepsala.
Další blok kódu vymaže registr a zavolá metodu instance Register() na objektech Album.
[PublishedWork]::ClearRegistry()
$Albums.Register()
VERBOSE: Clearing PublishedWork registry
VERBOSE: Adding work 'The Dark Side of the Moon' to works list
VERBOSE: Adding artist 'Pink Floyd' to artists list
VERBOSE: Adding work 'The Wall' to works list
VERBOSE: Artist 'Pink Floyd' already registered.
VERBOSE: Adding work '36 Chambers' to works list
VERBOSE: Adding artist 'Wu-Tang Clan' to artists list
Metoda instance na Album objekty má stejný účinek jako volání statické metody na odvozené nebo základní třídy.
Následující blok kódu porovnává statické vlastnosti základní třídy a odvozené třídy, což ukazuje, že jsou stejné.
[pscustomobject]@{
'[PublishedWork]::List' = [PublishedWork]::List -join ",`n"
'[Album]::List' = [Album]::List -join ",`n"
'[PublishedWork]::Artists' = [PublishedWork]::Artists -join ",`n"
'[Album]::Artists' = [Album]::Artists -join ",`n"
'IsSame::List' = (
[PublishedWork]::List.Count -eq [Album]::List.Count -and
[PublishedWork]::List.ToString() -eq [Album]::List.ToString()
)
'IsSame::Artists' = (
[PublishedWork]::Artists.Count -eq [Album]::Artists.Count -and
[PublishedWork]::Artists.ToString() -eq [Album]::Artists.ToString()
)
} | Format-List
[PublishedWork]::List : The Dark Side of the Moon by Pink Floyd,
The Wall by Pink Floyd,
36 Chambers by Wu-Tang Clan
[Album]::List : The Dark Side of the Moon by Pink Floyd,
The Wall by Pink Floyd,
36 Chambers by Wu-Tang Clan
[PublishedWork]::Artists : Pink Floyd,
Wu-Tang Clan
[Album]::Artists : Pink Floyd,
Wu-Tang Clan
IsSame::List : True
IsSame::Artists : True
Definování odvozené třídy s přepsáními
Další blok kódu definuje třídu Ilustrace dědění ze základní třídy PublishedWork třídy. Nová třída rozšiřuje základní třídu definováním vlastnosti instance Medium s výchozí hodnotou Unknown.
Na rozdíl od odvozené třídy AlbumIlustrace přepíše následující vlastnosti a metody:
- Přepíše statickou vlastnost Artists. Definice je stejná, ale Ilustrace třída ji deklaruje přímo.
- Přepíše vlastnost Category instance a nastaví výchozí hodnotu na
Illustrations. - Přepíše metodu
ToString()instance tak, aby řetězcová reprezentace obrázku zahrnovala médium, se kterým byla vytvořena.
Třída také definuje statickou RegisterIllustration() metodu, která nejprve zavolá základní třídu RegisterWork() metodu a pak přidá interpreta do přepsané Artists statickou vlastnost odvozené třídy.
Nakonec třída přepíše všechny tři konstruktory:
- Výchozí konstruktor je prázdný s výjimkou podrobné zprávy označující, že vytvořil obrázek.
- Další konstruktor přebírá dvě řetězcové hodnoty pro název a interpreta, který vytvořil ilustraci. Místo implementace logiky pro nastavení Name a Artist vlastnosti, konstruktor volá příslušný konstruktor ze základní třídy.
- Poslední konstruktor přebírá tři řetězcové hodnoty pro název, interpreta a médium obrázku. Oba konstruktory zapisují podrobnou zprávu označující, že vytvořily obrázek.
class Illustration : PublishedWork {
static [string[]] $Artists = @()
static [void] RegisterIllustration([Illustration]$Work) {
$wArtist = $Work.Artist
[PublishedWork]::RegisterWork($Work)
if ($wArtist -notin [Illustration]::Artists) {
Write-Verbose "Adding illustrator '$wArtist' to artists list"
[Illustration]::Artists += $wArtist
} else {
Write-Verbose "Illustrator '$wArtist' already registered."
}
}
[string] $Category = 'Illustrations'
[string] $Medium = 'Unknown'
[string] ToString() {
return "$($this.Name) by $($this.Artist) ($($this.Medium))"
}
Illustration() {
Write-Verbose 'Defined an illustration'
}
Illustration([string]$Name, [string]$Artist) : base($Name, $Artist) {
Write-Verbose "Defined '$Name' by $Artist ($($this.Medium)) as an illustration"
}
Illustration([string]$Name, [string]$Artist, [string]$Medium) {
$this.Name = $Name
$this.Artist = $Artist
$this.Medium = $Medium
Write-Verbose "Defined '$Name' by $Artist ($Medium) as an illustration"
}
}
Následující blok kódu ukazuje chování odvozené Ilustrace třídy. Vytvoří tři instance třídy, zobrazí je v tabulce a pak je zaregistruje pomocí zděděné statické RegisterWork() metody. Potom volá stejnou statickou metodu přímo v základní třídě. Nakonec zapíše zprávy zobrazující seznam registrovaných umělců pro základní třídu a odvozenou třídu.
$Illustrations = @(
[Illustration]@{
Name = 'The Funny Thing'
Artist = 'Wanda Gág'
Medium = 'Lithography'
}
[Illustration]::new('Millions of Cats', 'Wanda Gág')
[Illustration]::new(
'The Lion and the Mouse',
'Jerry Pinkney',
'Watercolor'
)
)
$Illustrations | Format-Table
$Illustrations | ForEach-Object { [Illustration]::RegisterIllustration($_) }
$Illustrations | ForEach-Object { [PublishedWork]::RegisterWork($_) }
"Published work artists: $([PublishedWork]::Artists -join ', ')"
"Illustration artists: $([Illustration]::Artists -join ', ')"
VERBOSE: Defined a published work of type [Illustration]
VERBOSE: Defined an illustration
VERBOSE: Defined 'Millions of Cats' by Wanda Gág as a published work of type [Illustration]
VERBOSE: Defined 'Millions of Cats' by Wanda Gág (Unknown) as an illustration
VERBOSE: Defined a published work of type [Illustration]
VERBOSE: Defined 'The Lion and the Mouse' by Jerry Pinkney (Watercolor) as an illustration
Category Medium Name Artist
-------- ------ ---- ------
Illustrations Lithography The Funny Thing Wanda Gág
Illustrations Unknown Millions of Cats Wanda Gág
Illustrations Watercolor The Lion and the Mouse Jerry Pinkney
VERBOSE: Adding work 'The Funny Thing' to works list
VERBOSE: Adding artist 'Wanda Gág' to artists list
VERBOSE: Adding illustrator 'Wanda Gág' to artists list
VERBOSE: Adding work 'Millions of Cats' to works list
VERBOSE: Artist 'Wanda Gág' already registered.
VERBOSE: Illustrator 'Wanda Gág' already registered.
VERBOSE: Adding work 'The Lion and the Mouse' to works list
VERBOSE: Adding artist 'Jerry Pinkney' to artists list
VERBOSE: Adding illustrator 'Jerry Pinkney' to artists list
VERBOSE: Work 'The Funny Thing' already registered.
VERBOSE: Artist 'Wanda Gág' already registered.
VERBOSE: Work 'Millions of Cats' already registered.
VERBOSE: Artist 'Wanda Gág' already registered.
VERBOSE: Work 'The Lion and the Mouse' already registered.
VERBOSE: Artist 'Jerry Pinkney' already registered.
Published work artists: Pink Floyd, Wu-Tang Clan, Wanda Gág, Jerry Pinkney
Illustration artists: Wanda Gág, Jerry Pinkney
Podrobné zasílání zpráv z vytváření instancí ukazuje, že:
- Při vytváření první instance byl výchozí konstruktor základní třídy volána před výchozí konstruktor odvozené třídy.
- Při vytváření druhé instance byl explicitně zděděný konstruktor volána pro základní třídu před konstruktor odvozené třídy.
- Při vytváření třetí instance byl výchozí konstruktor základní třídy volána před konstruktor odvozené třídy.
Podrobné zprávy z metody RegisterWork() označují, že díla a umělci již byli zaregistrováni. Důvodem je to, že RegisterIllustration() metoda volala interně metodu RegisterWork().
Při porovnávání hodnoty statické Artist vlastnost pro základní i odvozenou třídu jsou však hodnoty odlišné. Vlastnost Artists pro odvozenou třídu zahrnuje pouze ilustrátory, ne umělce alba. Redefining Artist vlastnost v odvozené třídě zabraňuje třídy vrátit statickou vlastnost základní třídy.
Poslední blok kódu volá metodu ToString() pro položky statické List vlastnost základní třídy.
[PublishedWork]::List | ForEach-Object -Process { $_.ToString() }
The Dark Side of the Moon by Pink Floyd
The Wall by Pink Floyd
36 Chambers by Wu-Tang Clan
The Funny Thing by Wanda Gág (Lithography)
Millions of Cats by Wanda Gág (Unknown)
The Lion and the Mouse by Jerry Pinkney (Watercolor)
Instance Album vrátí pouze jméno a interpreta v řetězci.
Ilustrace instance zahrnovaly také médium v závorkách, protože tato třída překročila ToString() metodu.
Příklad 2 – Implementace rozhraní
Následující příklad ukazuje, jak může třída implementovat jedno nebo více rozhraní. Příklad rozšiřuje definici třídy Temperature, aby podporovala více operací a chování.
Definice počáteční třídy
Před implementací rozhraní je třída Teplota definována se dvěma vlastnostmi, Stupňů a Měřítko. Definuje konstruktory a tři metody instance pro vrácení instance ve stupních konkrétního škálování.
Třída definuje dostupná měřítka pomocí TemperatureScale výčtu.
class Temperature {
[float] $Degrees
[TemperatureScale] $Scale
Temperature() {}
Temperature([float] $Degrees) { $this.Degrees = $Degrees }
Temperature([TemperatureScale] $Scale) { $this.Scale = $Scale }
Temperature([float] $Degrees, [TemperatureScale] $Scale) {
$this.Degrees = $Degrees
$this.Scale = $Scale
}
[float] ToKelvin() {
switch ($this.Scale) {
Celsius { return $this.Degrees + 273.15 }
Fahrenheit { return ($this.Degrees + 459.67) * 5/9 }
}
return $this.Degrees
}
[float] ToCelsius() {
switch ($this.Scale) {
Fahrenheit { return ($this.Degrees - 32) * 5/9 }
Kelvin { return $this.Degrees - 273.15 }
}
return $this.Degrees
}
[float] ToFahrenheit() {
switch ($this.Scale) {
Celsius { return $this.Degrees * 9/5 + 32 }
Kelvin { return $this.Degrees * 9/5 - 459.67 }
}
return $this.Degrees
}
}
enum TemperatureScale {
Celsius = 0
Fahrenheit = 1
Kelvin = 2
}
V této základní implementaci však existuje několik omezení, jak je znázorněno v následujícím příkladu výstupu:
$Celsius = [Temperature]::new()
$Fahrenheit = [Temperature]::new([TemperatureScale]::Fahrenheit)
$Kelvin = [Temperature]::new(0, 'Kelvin')
$Celsius, $Fahrenheit, $Kelvin
"The temperatures are: $Celsius, $Fahrenheit, $Kelvin"
[Temperature]::new() -eq $Celsius
$Celsius -gt $Kelvin
Degrees Scale
------- -----
0.00 Celsius
0.00 Fahrenheit
0.00 Kelvin
The temperatures are: Temperature, Temperature, Temperature
False
InvalidOperation:
Line |
11 | $Celsius -gt $Kelvin
| ~~~~~~~~~~~~~~~~~~~~
| Cannot compare "Temperature" because it is not IComparable.
Výstup ukazuje, že instance Teplotní:
- Nezobrazujte se správně jako řetězce.
- Nelze správně zkontrolovat ekvivalenci.
- Nedá se porovnat.
Tyto tři problémy je možné vyřešit implementací rozhraní pro třídu.
Implementace IFormattable
První rozhraní pro implementaci pro Temperature třída je System.IFormattable. Toto rozhraní umožňuje formátování instance třídy jako různých řetězců. Aby bylo možné implementovat rozhraní, třída musí dědit z System.IFormattable a definovat ToString() instance metoda.
Metoda instance ToString() musí mít následující podpis:
[string] ToString(
[string]$Format,
[System.IFormatProvider]$FormatProvider
) {
# Implementation
}
Podpis, který rozhraní vyžaduje, je uveden v referenční dokumentaci .
Pro teplotníby třída měla podporovat tři formáty: C vrátit instanci ve Stupních Celsia, F vrátit v Fahrenheita a K vrátit instanci v Kelvinu. Pro jakýkoli jiný formát by metoda měla vyvolat System.FormatException.
[string] ToString(
[string]$Format,
[System.IFormatProvider]$FormatProvider
) {
# If format isn't specified, use the defined scale.
if ([string]::IsNullOrEmpty($Format)) {
$Format = switch ($this.Scale) {
Celsius { 'C' }
Fahrenheit { 'F' }
Kelvin { 'K' }
}
}
# If format provider isn't specified, use the current culture.
if ($null -eq $FormatProvider) {
$FormatProvider = [cultureinfo]::CurrentCulture
}
# Format the temperature.
switch ($Format) {
'C' {
return $this.ToCelsius().ToString('F2', $FormatProvider) + '°C'
}
'F' {
return $this.ToFahrenheit().ToString('F2', $FormatProvider) + '°F'
}
'K' {
return $this.ToKelvin().ToString('F2', $FormatProvider) + '°K'
}
}
# If we get here, the format is invalid.
throw [System.FormatException]::new(
"Unknown format: '$Format'. Valid Formats are 'C', 'F', and 'K'"
)
}
V této implementaci metoda ve výchozím nastavení škáluje instanci pro formát a aktuální jazykovou verzi při formátování samotné hodnoty číselného stupně. Používá To<Scale>() metody instance k převodu stupňů, jejich formátování na dvě desetinná místa a připojí příslušný symbol stupně k řetězci.
S implementovaným požadovaným podpisem může třída také definovat přetížení, aby bylo snazší vrátit formátovanou instanci.
[string] ToString([string]$Format) {
return $this.ToString($Format, $null)
}
[string] ToString() {
return $this.ToString($null, $null)
}
Následující kód ukazuje aktualizovanou definici Temperature:
class Temperature : System.IFormattable {
[float] $Degrees
[TemperatureScale] $Scale
Temperature() {}
Temperature([float] $Degrees) { $this.Degrees = $Degrees }
Temperature([TemperatureScale] $Scale) { $this.Scale = $Scale }
Temperature([float] $Degrees, [TemperatureScale] $Scale) {
$this.Degrees = $Degrees
$this.Scale = $Scale
}
[float] ToKelvin() {
switch ($this.Scale) {
Celsius { return $this.Degrees + 273.15 }
Fahrenheit { return ($this.Degrees + 459.67) * 5 / 9 }
}
return $this.Degrees
}
[float] ToCelsius() {
switch ($this.Scale) {
Fahrenheit { return ($this.Degrees - 32) * 5 / 9 }
Kelvin { return $this.Degrees - 273.15 }
}
return $this.Degrees
}
[float] ToFahrenheit() {
switch ($this.Scale) {
Celsius { return $this.Degrees * 9 / 5 + 32 }
Kelvin { return $this.Degrees * 9 / 5 - 459.67 }
}
return $this.Degrees
}
[string] ToString(
[string]$Format,
[System.IFormatProvider]$FormatProvider
) {
# If format isn't specified, use the defined scale.
if ([string]::IsNullOrEmpty($Format)) {
$Format = switch ($this.Scale) {
Celsius { 'C' }
Fahrenheit { 'F' }
Kelvin { 'K' }
}
}
# If format provider isn't specified, use the current culture.
if ($null -eq $FormatProvider) {
$FormatProvider = [cultureinfo]::CurrentCulture
}
# Format the temperature.
switch ($Format) {
'C' {
return $this.ToCelsius().ToString('F2', $FormatProvider) + '°C'
}
'F' {
return $this.ToFahrenheit().ToString('F2', $FormatProvider) + '°F'
}
'K' {
return $this.ToKelvin().ToString('F2', $FormatProvider) + '°K'
}
}
# If we get here, the format is invalid.
throw [System.FormatException]::new(
"Unknown format: '$Format'. Valid Formats are 'C', 'F', and 'K'"
)
}
[string] ToString([string]$Format) {
return $this.ToString($Format, $null)
}
[string] ToString() {
return $this.ToString($null, $null)
}
}
enum TemperatureScale {
Celsius = 0
Fahrenheit = 1
Kelvin = 2
}
Výstup přetížení metody je uveden v následujícím bloku.
$Temp = [Temperature]::new()
"The temperature is $Temp"
$Temp.ToString()
$Temp.ToString('K')
$Temp.ToString('F', $null)
The temperature is 0.00°C
0.00°C
273.15°K
32.00°F
Implementace IEquatable
Teď, když je možné naformátovat třídu Temperature pro čitelnost, musí uživatelé zkontrolovat, jestli jsou dvě instance třídy stejné. Aby bylo možné tento test podporovat, třída musí implementovat rozhraní System.IEquatable.
Aby bylo možné implementovat rozhraní, třída musí dědit z System.IEquatable a definovat Equals() instance metoda. Metoda Equals() musí mít následující podpis:
[bool] Equals([Object]$Other) {
# Implementation
}
Podpis, který rozhraní vyžaduje, je uveden v referenční dokumentaci .
Pro Temperatureby třída měla podporovat pouze porovnání dvou instancí třídy. Pro jakoukoli jinou hodnotu nebo typ, včetně $null, by měl vrátit $false. Při porovnávání dvou teplot by metoda měla převést obě hodnoty na Kelvin, protože teploty mohou být ekvivalentní i s různými stupnici.
[bool] Equals([Object]$Other) {
# If the other object is null, we can't compare it.
if ($null -eq $Other) {
return $false
}
# If the other object isn't a temperature, we can't compare it.
$OtherTemperature = $Other -as [Temperature]
if ($null -eq $OtherTemperature) {
return $false
}
# Compare the temperatures as Kelvin.
return $this.ToKelvin() -eq $OtherTemperature.ToKelvin()
}
Při implementaci metody rozhraní je aktualizovaná definice Temperature:
class Temperature : System.IFormattable, System.IEquatable[Object] {
[float] $Degrees
[TemperatureScale] $Scale
Temperature() {}
Temperature([float] $Degrees) { $this.Degrees = $Degrees }
Temperature([TemperatureScale] $Scale) { $this.Scale = $Scale }
Temperature([float] $Degrees, [TemperatureScale] $Scale) {
$this.Degrees = $Degrees
$this.Scale = $Scale
}
[float] ToKelvin() {
switch ($this.Scale) {
Celsius { return $this.Degrees + 273.15 }
Fahrenheit { return ($this.Degrees + 459.67) * 5 / 9 }
}
return $this.Degrees
}
[float] ToCelsius() {
switch ($this.Scale) {
Fahrenheit { return ($this.Degrees - 32) * 5 / 9 }
Kelvin { return $this.Degrees - 273.15 }
}
return $this.Degrees
}
[float] ToFahrenheit() {
switch ($this.Scale) {
Celsius { return $this.Degrees * 9 / 5 + 32 }
Kelvin { return $this.Degrees * 9 / 5 - 459.67 }
}
return $this.Degrees
}
[string] ToString(
[string]$Format,
[System.IFormatProvider]$FormatProvider
) {
# If format isn't specified, use the defined scale.
if ([string]::IsNullOrEmpty($Format)) {
$Format = switch ($this.Scale) {
Celsius { 'C' }
Fahrenheit { 'F' }
Kelvin { 'K' }
}
}
# If format provider isn't specified, use the current culture.
if ($null -eq $FormatProvider) {
$FormatProvider = [cultureinfo]::CurrentCulture
}
# Format the temperature.
switch ($Format) {
'C' {
return $this.ToCelsius().ToString('F2', $FormatProvider) + '°C'
}
'F' {
return $this.ToFahrenheit().ToString('F2', $FormatProvider) + '°F'
}
'K' {
return $this.ToKelvin().ToString('F2', $FormatProvider) + '°K'
}
}
# If we get here, the format is invalid.
throw [System.FormatException]::new(
"Unknown format: '$Format'. Valid Formats are 'C', 'F', and 'K'"
)
}
[string] ToString([string]$Format) {
return $this.ToString($Format, $null)
}
[string] ToString() {
return $this.ToString($null, $null)
}
[bool] Equals([Object]$Other) {
# If the other object is null, we can't compare it.
if ($null -eq $Other) {
return $false
}
# If the other object isn't a temperature, we can't compare it.
$OtherTemperature = $Other -as [Temperature]
if ($null -eq $OtherTemperature) {
return $false
}
# Compare the temperatures as Kelvin.
return $this.ToKelvin() -eq $OtherTemperature.ToKelvin()
}
}
enum TemperatureScale {
Celsius = 0
Fahrenheit = 1
Kelvin = 2
}
Následující blok ukazuje, jak se aktualizovaná třída chová:
$Celsius = [Temperature]::new()
$Fahrenheit = [Temperature]::new(32, 'Fahrenheit')
$Kelvin = [Temperature]::new([TemperatureScale]::Kelvin)
@"
Temperatures are: $Celsius, $Fahrenheit, $Kelvin
`$Celsius.Equals(`$Fahrenheit) = $($Celsius.Equals($Fahrenheit))
`$Celsius -eq `$Fahrenheit = $($Celsius -eq $Fahrenheit)
`$Celsius -ne `$Kelvin = $($Celsius -ne $Kelvin)
"@
Temperatures are: 0.00°C, 32.00°F, 0.00°K
$Celsius.Equals($Fahrenheit) = True
$Celsius -eq $Fahrenheit = True
$Celsius -ne $Kelvin = True
Implementace IComparable
Posledním rozhraním, které se má implementovat pro třídu Temperature je System.IComparable. Když třída implementuje toto rozhraní, mohou uživatelé použít -lt, -le, -gta -ge operátory k porovnání instancí třídy.
K implementaci rozhraní musí třída dědit z System.IComparable a definovat Equals() instance metoda. Metoda Equals() musí mít následující podpis:
[int] CompareTo([Object]$Other) {
# Implementation
}
Podpis, který rozhraní vyžaduje, je uveden v referenční dokumentaci .
Pro Temperatureby třída měla podporovat pouze porovnání dvou instancí třídy. Vzhledem k tomu, že základní typ Stupňů vlastnost, i když je převeden na jiné měřítko, je číslo s plovoucí desetinou čárkou, může metoda spoléhat na základní typ pro skutečné porovnání.
[int] CompareTo([Object]$Other) {
# If the other object's null, consider this instance "greater than" it
if ($null -eq $Other) {
return 1
}
# If the other object isn't a temperature, we can't compare it.
$OtherTemperature = $Other -as [Temperature]
if ($null -eq $OtherTemperature) {
throw [System.ArgumentException]::new(
"Object must be of type 'Temperature'."
)
}
# Compare the temperatures as Kelvin.
return $this.ToKelvin().CompareTo($OtherTemperature.ToKelvin())
}
Konečná definice třídy Temperature je:
class Temperature : System.IFormattable,
System.IComparable,
System.IEquatable[Object] {
# Instance properties
[float] $Degrees
[TemperatureScale] $Scale
# Constructors
Temperature() {}
Temperature([float] $Degrees) { $this.Degrees = $Degrees }
Temperature([TemperatureScale] $Scale) { $this.Scale = $Scale }
Temperature([float] $Degrees, [TemperatureScale] $Scale) {
$this.Degrees = $Degrees
$this.Scale = $Scale
}
[float] ToKelvin() {
switch ($this.Scale) {
Celsius { return $this.Degrees + 273.15 }
Fahrenheit { return ($this.Degrees + 459.67) * 5 / 9 }
}
return $this.Degrees
}
[float] ToCelsius() {
switch ($this.Scale) {
Fahrenheit { return ($this.Degrees - 32) * 5 / 9 }
Kelvin { return $this.Degrees - 273.15 }
}
return $this.Degrees
}
[float] ToFahrenheit() {
switch ($this.Scale) {
Celsius { return $this.Degrees * 9 / 5 + 32 }
Kelvin { return $this.Degrees * 9 / 5 - 459.67 }
}
return $this.Degrees
}
[string] ToString(
[string]$Format,
[System.IFormatProvider]$FormatProvider
) {
# If format isn't specified, use the defined scale.
if ([string]::IsNullOrEmpty($Format)) {
$Format = switch ($this.Scale) {
Celsius { 'C' }
Fahrenheit { 'F' }
Kelvin { 'K' }
}
}
# If format provider isn't specified, use the current culture.
if ($null -eq $FormatProvider) {
$FormatProvider = [cultureinfo]::CurrentCulture
}
# Format the temperature.
switch ($Format) {
'C' {
return $this.ToCelsius().ToString('F2', $FormatProvider) + '°C'
}
'F' {
return $this.ToFahrenheit().ToString('F2', $FormatProvider) + '°F'
}
'K' {
return $this.ToKelvin().ToString('F2', $FormatProvider) + '°K'
}
}
# If we get here, the format is invalid.
throw [System.FormatException]::new(
"Unknown format: '$Format'. Valid Formats are 'C', 'F', and 'K'"
)
}
[string] ToString([string]$Format) {
return $this.ToString($Format, $null)
}
[string] ToString() {
return $this.ToString($null, $null)
}
[bool] Equals([Object]$Other) {
# If the other object is null, we can't compare it.
if ($null -eq $Other) {
return $false
}
# If the other object isn't a temperature, we can't compare it.
$OtherTemperature = $Other -as [Temperature]
if ($null -eq $OtherTemperature) {
return $false
}
# Compare the temperatures as Kelvin.
return $this.ToKelvin() -eq $OtherTemperature.ToKelvin()
}
[int] CompareTo([Object]$Other) {
# If the other object's null, consider this instance "greater than" it
if ($null -eq $Other) {
return 1
}
# If the other object isn't a temperature, we can't compare it.
$OtherTemperature = $Other -as [Temperature]
if ($null -eq $OtherTemperature) {
throw [System.ArgumentException]::new(
"Object must be of type 'Temperature'."
)
}
# Compare the temperatures as Kelvin.
return $this.ToKelvin().CompareTo($OtherTemperature.ToKelvin())
}
}
enum TemperatureScale {
Celsius = 0
Fahrenheit = 1
Kelvin = 2
}
S úplnou definicí můžou uživatelé formátovat a porovnávat instance třídy v PowerShellu jako jakýkoli integrovaný typ.
$Celsius = [Temperature]::new()
$Fahrenheit = [Temperature]::new(32, 'Fahrenheit')
$Kelvin = [Temperature]::new([TemperatureScale]::Kelvin)
@"
Temperatures are: $Celsius, $Fahrenheit, $Kelvin
`$Celsius.Equals(`$Fahrenheit) = $($Celsius.Equals($Fahrenheit))
`$Celsius.Equals(`$Kelvin) = $($Celsius.Equals($Kelvin))
`$Celsius.CompareTo(`$Fahrenheit) = $($Celsius.CompareTo($Fahrenheit))
`$Celsius.CompareTo(`$Kelvin) = $($Celsius.CompareTo($Kelvin))
`$Celsius -lt `$Fahrenheit = $($Celsius -lt $Fahrenheit)
`$Celsius -le `$Fahrenheit = $($Celsius -le $Fahrenheit)
`$Celsius -eq `$Fahrenheit = $($Celsius -eq $Fahrenheit)
`$Celsius -gt `$Kelvin = $($Celsius -gt $Kelvin)
"@
Temperatures are: 0.00°C, 32.00°F, 0.00°K
$Celsius.Equals($Fahrenheit) = True
$Celsius.Equals($Kelvin) = False
$Celsius.CompareTo($Fahrenheit) = 0
$Celsius.CompareTo($Kelvin) = 1
$Celsius -lt $Fahrenheit = False
$Celsius -le $Fahrenheit = True
$Celsius -eq $Fahrenheit = True
$Celsius -gt $Kelvin = True
Příklad 3 – Dědění z obecné základní třídy
Tento příklad ukazuje, jak lze odvodit z obecného typu, pokud je parametr typu již definován v době analýzy.
Použití předdefinované třídy jako parametru typu
Spusťte následující blok kódu. Ukazuje, jak může nová třída dědit z obecného typu, pokud je parametr typu již definován v době analýzy.
class ExampleStringList : System.Collections.Generic.List[string] {}
$List = [ExampleStringList]::new()
$List.AddRange([string[]]@('a','b','c'))
$List.GetType() | Format-List -Property Name, BaseType
$List
Name : ExampleStringList
BaseType : System.Collections.Generic.List`1[System.String]
a
b
c
Použití vlastní třídy jako parametru typu
Další blok kódu nejprve definuje novou třídu, ExampleItem, s jednou instancí vlastnost a ToString() metoda. Pak definuje ExampleItemList třídy dědění z třídy System.Collections.Generic.List základní třídu s ExampleItem jako parametr typu.
Zkopírujte celý blok kódu a spusťte ho jako jeden příkaz.
class ExampleItem {
[string] $Name
[string] ToString() { return $this.Name }
}
class ExampleItemList : System.Collections.Generic.List[ExampleItem] {}
ParentContainsErrorRecordException: An error occurred while creating the pipeline.
Spuštění celého bloku kódu vyvolá chybu, protože PowerShell ještě nenačetl třídu ExampleItem do modulu runtime. Název třídy nelze použít jako parametr typu pro System.Collections.Generic.List základní třídu.
Spusťte následující bloky kódu v pořadí, v jakém jsou definované.
class ExampleItem {
[string] $Name
[string] ToString() { return $this.Name }
}
class ExampleItemList : System.Collections.Generic.List[ExampleItem] {}
Tentokrát PowerShell nevyvolá žádné chyby. Obě třídy jsou nyní definovány. Spuštěním následujícího bloku kódu zobrazte chování nové třídy.
$List = [ExampleItemList]::new()
$List.AddRange([ExampleItem[]]@(
[ExampleItem]@{ Name = 'Foo' }
[ExampleItem]@{ Name = 'Bar' }
[ExampleItem]@{ Name = 'Baz' }
))
$List.GetType() | Format-List -Property Name, BaseType
$List
Name : ExampleItemList
BaseType : System.Collections.Generic.List`1[ExampleItem]
Name
----
Foo
Bar
Baz
Odvození obecného s parametrem vlastního typu v modulu
Následující bloky kódu ukazují, jak můžete definovat třídu, která dědí z obecné základní třídy, která používá vlastní typ pro parametr typu.
Uložte následující blok kódu jako GenericExample.psd1.
@{
RootModule = 'GenericExample.psm1'
ModuleVersion = '0.1.0'
GUID = '2779fa60-0b3b-4236-b592-9060c0661ac2'
}
Uložte následující blok kódu jako GenericExample.InventoryItem.psm1.
class InventoryItem {
[string] $Name
[int] $Count
InventoryItem() {}
InventoryItem([string]$Name) {
$this.Name = $Name
}
InventoryItem([string]$Name, [int]$Count) {
$this.Name = $Name
$this.Count = $Count
}
[string] ToString() {
return "$($this.Name) ($($this.Count))"
}
}
Uložte následující blok kódu jako GenericExample.psm1.
using namespace System.Collections.Generic
using module ./GenericExample.InventoryItem.psm1
class Inventory : List[InventoryItem] {}
# Define the types to export with type accelerators.
$ExportableTypes =@(
[InventoryItem]
[Inventory]
)
# Get the internal TypeAccelerators class to use its static methods.
$TypeAcceleratorsClass = [psobject].Assembly.GetType(
'System.Management.Automation.TypeAccelerators'
)
# Ensure none of the types would clobber an existing type accelerator.
# If a type accelerator with the same name exists, throw an exception.
$ExistingTypeAccelerators = $TypeAcceleratorsClass::Get
foreach ($Type in $ExportableTypes) {
if ($Type.FullName -in $ExistingTypeAccelerators.Keys) {
$Message = @(
"Unable to register type accelerator '$($Type.FullName)'"
'Accelerator already exists.'
) -join ' - '
throw [System.Management.Automation.ErrorRecord]::new(
[System.InvalidOperationException]::new($Message),
'TypeAcceleratorAlreadyExists',
[System.Management.Automation.ErrorCategory]::InvalidOperation,
$Type.FullName
)
}
}
# Add type accelerators for every exportable type.
foreach ($Type in $ExportableTypes) {
$TypeAcceleratorsClass::Add($Type.FullName, $Type)
}
# Remove type accelerators when the module is removed.
$MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = {
foreach($Type in $ExportableTypes) {
$TypeAcceleratorsClass::Remove($Type.FullName)
}
}.GetNewClosure()
Spropitné
Kořenový modul přidá vlastní typy do akcelerátorů typů PowerShellu. Tento model umožňuje uživatelům modulu okamžitě získat přístup k IntelliSense a automatickému dokončování pro vlastní typy, aniž by museli nejprve použít příkaz using module.
Další informace o tomto vzoru naleznete v části Export s akcelerátory typů about_Classes.
Importujte modul a ověřte výstup.
Import-Module ./GenericExample.psd1
$Inventory = [Inventory]::new()
$Inventory.GetType() | Format-List -Property Name, BaseType
$Inventory.Add([InventoryItem]::new('Bucket', 2))
$Inventory.Add([InventoryItem]::new('Mop'))
$Inventory.Add([InventoryItem]@{ Name = 'Broom' ; Count = 4 })
$Inventory
Name : Inventory
BaseType : System.Collections.Generic.List`1[InventoryItem]
Name Count
---- -----
Bucket 2
Mop 0
Broom 4
Modul se načte bez chyb, protože třída InventoryItem je definována v jiném souboru modulu, než je třída Inventory. Obě třídy jsou k dispozici pro uživatele modulů.
Dědění základní třídy
Když třída dědí ze základní třídy, dědí vlastnosti a metody základní třídy. Nedědí konstruktory základní třídy přímo, ale může je volat.
Pokud je základní třída definována v .NET místo PowerShellu, mějte na paměti, že:
- Třídy PowerShellu nemůžou dědit z zapečetěných tříd.
- Při dědění z obecné základní třídy nemůže být parametr typu pro obecnou třídu odvozenou třídou. Použití odvozené třídy jako parametru typu vyvolá chybu analýzy.
Pokud chcete zjistit, jak dědičnost a přepsání funguje pro odvozené třídy, přečtěte si Příklad 1.
Odvozené konstruktory tříd
Odvozené třídy nedědí přímo konstruktory základní třídy. Pokud základní třída definuje výchozí konstruktor a odvozená třída nedefinuje žádné konstruktory, nové instance odvozené třídy používají výchozí konstruktor základní třídy. Pokud základní třída nedefinuje výchozí konstruktor, odvozená třída musí explicitně definovat alespoň jeden konstruktor.
Odvozené konstruktory třídy mohou vyvolat konstruktor ze základní třídy s base klíčové slovo. 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.
Ilustrace třída v Příklad 1 ukazuje, jak odvozená třída může používat konstruktory základní třídy.
Metody odvozené třídy
Když třída je odvozena ze základní třídy, dědí metody základní třídy a jejich přetížení. Všechny přetížení metody definované na základní třídě, včetně skrytých metod, jsou k dispozici v odvozené třídě.
Odvozená třída může přepsat přetížení zděděné metody opětovným definováním v definici třídy. Chcete-li přepsat přetížení, musí být typy parametrů stejné jako pro základní třídu. Typ výstupu přetížení se může lišit.
Na rozdíl od konstruktorů nemohou metody použít syntaxi : base(<parameters>) k vyvolání přetížení základní třídy pro metodu. Redefined přetížení odvozené třídy zcela nahrazuje přetížení definované základní třídou. Chcete-li volat metodu základní třídy pro instanci, přetypujte proměnnou instance ($this) na základní třídu před voláním metody.
Následující fragment kódu ukazuje, jak odvozená třída může volat metodu základní třídy.
class BaseClass {
[bool] IsTrue() { return $true }
}
class DerivedClass : BaseClass {
[bool] IsTrue() { return $false }
[bool] BaseIsTrue() { return ([BaseClass]$this).IsTrue() }
}
@"
[BaseClass]::new().IsTrue() = $([BaseClass]::new().IsTrue())
[DerivedClass]::new().IsTrue() = $([DerivedClass]::new().IsTrue())
[DerivedClass]::new().BaseIsTrue() = $([DerivedClass]::new().BaseIsTrue())
"@
[BaseClass]::new().IsTrue() = True
[DerivedClass]::new().IsTrue() = False
[DerivedClass]::new().BaseIsTrue() = True
Rozšířená ukázka znázorňující, jak odvozená třída může přepsat zděděné metody, naleznete v Ilustrace třídy v Příklad 1.
Odvozené vlastnosti třídy
Když třída je odvozena od základní třídy, dědí vlastnosti základní třídy. Všechny vlastnosti definované v základní třídě, včetně skrytých vlastností, jsou k dispozici v odvozené třídě.
Odvozená třída může přepsat zděděnou vlastnost tím, že ji předefinuje v definici třídy. Vlastnost odvozené třídy používá redefinovaný typ a výchozí hodnotu, pokud existuje. Pokud zděděná vlastnost definovala výchozí hodnotu a předdefinovaná vlastnost ne, zděděná vlastnost nemá žádnou výchozí hodnotu.
Pokud odvozená třída nepřepíše statickou vlastnost, přístup ke statické vlastnosti prostřednictvím odvozené třídy přistupuje ke statické vlastnosti základní třídy. Úprava hodnoty vlastnosti prostřednictvím odvozené třídy upraví hodnotu základní třídy. Všechny ostatní odvozené třídy, které nepřepíší statickou vlastnost, také používá hodnotu vlastnosti základní třídy. Aktualizace hodnoty zděděné statické vlastnosti ve třídě, která nepřepíše vlastnost, může mít nezamýšlené účinky pro třídy odvozené ze stejné základní třídy.
Příklad 1 ukazuje, jak odvozené třídy dědí, rozšiřují a přepisují vlastnosti základní třídy.
Odvození z obecných typů
Pokud třída je odvozena od obecného, musí být parametr typu již definován před tím, než PowerShell parsuje odvozenou třídu. Pokud je parametr typu pro obecný třída PowerShellu nebo výčet definovaný ve stejném souboru nebo bloku kódu, PowerShell vyvolá chybu.
Chcete-li odvodit třídu z obecné základní třídy s vlastním typem jako parametr typu, definujte třídu nebo výčet parametru typu v jiném souboru nebo modulu a pomocí příkazu using module načtěte definici typu.
Příklad znázorňující, jak dědit z obecné základní třídy, viz Příklad 3.
Užitečné třídy pro dědění
Existuje několik tříd, které mohou být užitečné dědit při vytváření modulů PowerShellu. Tato část uvádí několik základních tříd a třídy odvozené z nich lze použít.
- System.Attribute – Odvození tříd definující atributy, které lze použít pro proměnné, parametry, definice tříd a výčtů a další.
- System.Management.Automation.ArgumentTransformationAttribute – Odvození tříd pro zpracování převodu vstupu proměnné nebo parametru na konkrétní datový typ.
- System.Management.Automation.ValidateArgumentsAttribute – odvození tříd, které použijí vlastní ověřování na proměnné, parametry a vlastnosti třídy.
- System.Collections.Generic.List – odvození tříd, které usnadňují vytváření a správu seznamů určitého datového typu.
- System.Exception – odvození tříd pro definování vlastních chyb
Implementace rozhraní
Třída PowerShellu, která implementuje rozhraní, musí implementovat všechny členy tohoto rozhraní. Vynechání členů rozhraní implementace způsobí chybu parsování času ve skriptu.
Poznámka
PowerShell nepodporuje deklarování nových rozhraní ve skriptu PowerShellu.
Místo toho musí být rozhraní deklarována v kódu .NET a přidána do relace pomocí rutiny Add-Type nebo příkazu using assembly.
Když třída implementuje rozhraní, lze ji použít jako jakoukoli jinou třídu, která implementuje toto rozhraní. Některé příkazy a operace omezují jejich podporované typy na třídy, které implementují konkrétní rozhraní.
Pokud chcete zkontrolovat ukázkovou implementaci rozhraní, podívejte se na Příklad 2.
Užitečná rozhraní pro implementaci
Existuje několik tříd rozhraní, které mohou být užitečné dědit při vytváření modulů PowerShellu. Tato část uvádí několik základních tříd a třídy odvozené z nich lze použít.
- System.IEquatable – toto rozhraní umožňuje uživatelům porovnat dvě instance třídy. Pokud třída toto rozhraní neimplementuje, PowerShell kontroluje ekvivalenci mezi dvěma instancemi pomocí rovnosti odkazů. Jinými slovy, instance třídy se rovná pouze sobě, i když jsou hodnoty vlastností ve dvou instancích stejné.
-
System.IComparable – toto rozhraní umožňuje uživatelům porovnávat instance třídy s operátory porovnání
-le,-lt,-gea-gt. Pokud třída toto rozhraní neimplementuje, tyto operátory vyvolá chybu. - System.IFormattable – toto rozhraní umožňuje uživatelům formátovat instance třídy do různých řetězců. To je užitečné pro třídy, které mají více než jednu standardní řetězcovou reprezentaci, jako jsou rozpočtové položky, bibliografie a teploty.
- System.IConvertible – toto rozhraní umožňuje uživatelům převádět instance třídy na jiné typy modulu runtime. To je užitečné pro třídy, které mají základní číselnou hodnotu nebo lze převést na jednu.
Omezení
PowerShell nepodporuje definování rozhraní v kódu skriptu.
Alternativní řešení: Definujte rozhraní v jazyce C# a odkazujte na sestavení, které definuje rozhraní.
Třídy PowerShellu mohou dědit pouze z jedné základní třídy.
Alternativní řešení: Dědičnost tříd je tranzitivní. Odvozená třída může dědit z jiné odvozené třídy získat vlastnosti a metody základní třídy.
Při dědění z obecné třídy nebo rozhraní musí být parametr typu pro obecný již definován. Třída nemůže definovat sama sebe jako parametr typu pro třídu nebo rozhraní.
Alternativní řešení: Chcete-li odvodit z obecné základní třídy nebo rozhraní, definujte vlastní typ v jiném
.psm1souboru a pomocí příkazuusing modulenačtěte typ. Neexistuje žádné alternativní řešení pro použití vlastního typu jako parametru typu při dědění z obecného typu.