Megosztás a következőn keresztül:


az_öröklés_osztályokról

Rövid leírás

Ismerteti, hogyan definiálhat más típusokat kiterjesztő osztályokat.

Hosszú leírás

A PowerShell osztályok támogatják öröklési, amely lehetővé teszi egy leszármazott osztály definiálását, amely újra felhasználja (örökli), kibővíti vagy módosítja a szülőosztály viselkedését. Az az osztály, amelynek tagjait öröklik, neve alaposztály. Az alaposztály tagjait öröklő osztályt származtatott osztálynaknevezzük.

A PowerShell csak az egyetlen öröklést támogatja. Egy osztály csak egyetlen osztálytól örökölhet. Az öröklés azonban tranzitív, amely lehetővé teszi egy öröklési hierarchia definiálását egy halmazhoz. Más szóval a D örökölhet a Ctípustól, amely a Btípustól örököl, amely az Aalaposztálytípustól örököl. Mivel az öröklés tranzitív, a A típusú tagjai elérhetők a Dtípus számára.

A származtatott osztályok nem öröklik az alaposztály összes tagját. A következő tagok nem öröklődnek:

  • Statikus konstruktorok, amelyek inicializálják egy osztály statikus adatait.
  • Példánykonstruktorok, amelyeket az osztály új példányának létrehozásához hív meg. Minden osztálynak saját konstruktorokat kell meghatároznia.

Az osztályokat egy meglévő osztályból származó új osztály létrehozásával bővítheti. A származtatott osztály örökli az alaposztály tulajdonságait és metódusait. Igény szerint hozzáadhatja vagy felülbírálhatja az alaposztálytagokat.

Az osztályok a szerződéseket meghatározó felületektől is örökölhetnek. Az interfésztől öröklő osztálynak implementálnia kell ezt a szerződést. Ha ez megtörténik, az osztály úgy használható, mint bármely más osztály, amely implementálja ezt a felületet. Ha egy osztály egy interfésztől öröklődik, de nem implementálja a felületet, a PowerShell elemzési hibát okoz az osztály számára.

Egyes PowerShell-operátorok egy adott felületet implementáló osztálytól függenek. A -eq operátor például csak akkor ellenőrzi a referenciaegyenlőséget, ha az osztály nem implementálja a System.IEquatable interfészt. A -le, -lt, -geés -gt operátorok csak az System.IComparable interfészt implementáló osztályokon dolgoznak.

A származtatott osztály a : szintaxist használja egy alaposztály kibővítéséhez vagy interfészek implementálásához. A származtatott osztálynak mindig a bal szélsőnek kell lennie az osztálydeklarációban.

Ez a példa az alapvető PowerShell-osztályöröklési szintaxist mutatja be.

class Derived : Base {...}

Ez a példa az öröklést mutatja be egy felületi deklarációval, amely az alaposztály után jön.

class Derived : Base, Interface {...}

Szemantika

Az osztályöröklés a következő szintaxisokat használja:

Egysoros szintaxis

class <derived-class-name> : <base-class-or-interface-name>[, <interface-name>...] {
    <derived-class-body>
}

Például:

# Base class only
class Derived : Base {...}
# Interface only
class Derived : System.IComparable {...}
# Base class and interface
class Derived : Base, System.IComparable {...}

Többsoros szintaxis

class <derived-class-name> : <base-class-or-interface-name>[,
    <interface-name>...] {
    <derived-class-body>
}

Például:

class Derived : Base,
                System.IComparable,
                System.IFormattable,
                System.IConvertible {
    # Derived class definition
}

Példák

1. példa – Egy alaposztály öröklése és felülírása

Az alábbi példa az örökölt tulajdonságok felülbírálással és anélküli viselkedését mutatja be. A leírás elolvasása után futtassa a kódblokkokat sorrendben.

Az alaposztály meghatározása

Az első kódblokk a PublishedWork definiálja alaposztályként. Két statikus tulajdonsággal rendelkezik, List és Artists. Ezután meghatározza a statikus RegisterWork() metódust, amely műveket ad hozzá a statikus Lista tulajdonsághoz, valamint a művészeket a Művészek tulajdonsághoz, és üzenetet ír a listák minden új bejegyzéséhez.

Az osztály három olyan példánytulajdonságokat határoz meg, amelyek egy közzétett munkát írnak le. Végül meghatározza a Register() és ToString() példány metódusait.

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)" }
}

Származtatott osztály definiálása felülbírálások nélkül

Az első származtatott osztály Album. Nem bírál felül tulajdonságokat vagy metódusokat. Hozzáad egy új példánytulajdonságot, Műfajok, amely nem létezik az alaposztályban.

class Album : PublishedWork {
    [string[]] $Genres   = @()
}

Az alábbi kódblokk a származtatott Album osztály viselkedését mutatja be. Először úgy állítja be a $VerbosePreference, hogy az osztály metódusaiból érkező üzenetek a konzolra kerüljenek. Létrehozza az osztály három példányát, megjeleníti őket egy táblában, majd regisztrálja őket az örökölt statikus RegisterWork() metódussal. Ezután közvetlenül ugyanazt a statikus metódust hívja meg az alaposztályon.

$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.

Figyelje meg, hogy annak ellenére, hogy a Album osztály nem definiált értéket Kategória vagy konstruktorok számára, a tulajdonságot az alaposztály alapértelmezett konstruktora definiálta.

A részletes üzenetküldésben a RegisterWork() metódus második hívása arról számol be, hogy a művek és a művészek már regisztrálva vannak. Annak ellenére, hogy a RegisterWork()-t először a származtatott Album osztályra hívták meg, az alap PublishedWork osztály örökölt statikus metódusát használta. Ez a metódus frissítette az alaposztály statikus Lista és Művész tulajdonságait, amelyeket a származtatott osztály nem írt felül.

A következő kódblokk törli a beállításjegyzéket, és meghívja a Register() példánymetódust a Album objektumokon.

[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

Az Album objektumok példánymetódusa ugyanolyan hatással van, mint a statikus metódus meghívása a származtatott vagy alaposztályon.

Az alábbi kódblokk az alaposztály és a származtatott osztály statikus tulajdonságait hasonlítja össze, és azt mutatja, hogy azonosak.

[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

Származtatott osztály definiálása felülbírálásokkal

A következő kódblokk a Ábra osztályt határozza meg, amely a PublishedWork alap osztálytól öröklődik. Az új osztály kibővíti az alaposztályt a Közepes példánytulajdonság alapértelmezett értékének Unknownmegadásával.

A származtatott Album osztálytól eltérően Illusztráció felülbírálja a következő tulajdonságokat és metódusokat:

  • Felülírja a statikus Művészek tulajdonságot. A definíció ugyanaz, de az Illusztráció osztály közvetlenül deklarálja azt.
  • Felülbírálja a Category instance tulajdonságot, és az alapértelmezett értéket Illustrationsértékre állítja.
  • Felülbírálja a ToString()-példány metódusát, így az ábrák szöveges ábrázolása tartalmazza a készítésükhöz használt médiumot.

Az osztály meghatározza a statikus RegisterIllustration() metódust, amely először meghívja az alaposztály RegisterWork() metódusát, majd hozzáadja a művészt a származtatott osztály felülírt statikus Művészek tulajdonságához.

Végül az osztály felülbírálja mindhárom konstruktort:

  1. Az alapértelmezett konstruktor üres, kivéve egy részletes üzenetet, amely azt jelzi, hogy illusztrációt hozott létre.
  2. A következő konstruktor két sztringértéket vesz fel az ábrát létrehozó név és művész számára. A Név és Művész tulajdonságok beállításának logikája helyett a konstruktor meghívja a megfelelő konstruktort az alaposztályból.
  3. Az utolsó konstruktor három sztringértéket vesz fel az ábra nevére, művészére és adathordozójára. Mindkét konstruktor részletes üzenetet ír, amely azt jelzi, hogy illusztrációt hoztak létre.
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"
    }
}

Az alábbi kódblokk a származtatott Illusztráció osztály viselkedését mutatja be. Létrehozza az osztály három példányát, megjeleníti őket egy táblában, majd regisztrálja őket az örökölt statikus RegisterWork() metódussal. Ezután közvetlenül ugyanazt a statikus metódust hívja meg az alaposztályon. Végül az alaposztályhoz és a származtatott osztályhoz regisztrált művészek listáját tartalmazó üzeneteket ír.

$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

A példányok létrehozásának részletes üzenete a következőt mutatja:

  • Az első példány létrehozásakor az alaposztály alapértelmezett konstruktora a származtatott osztály alapértelmezett konstruktora előtt lett meghívva.
  • A második példány létrehozásakor az expliciten örökölt konstruktort az alaposztály számára hívták meg a leszármazott osztály konstruktora előtt.
  • A harmadik példány létrehozásakor az alaposztály alapértelmezett konstruktorát a származtatott osztálykonstruktor előtt hívták meg.

A RegisterWork() metódus részletes üzenetei azt jelzik, hogy a műveket és a művészeket már regisztrálták. Ennek az az oka, hogy a RegisterIllustration() metódus belsőleg meghívja a RegisterWork() metódust.

Ha azonban a statikus Művész tulajdonság értékét hasonlítja össze az alaposztály és a származtatott osztály esetében, az értékek eltérőek. A Artists tulajdonsága a származtatott osztályhoz csak illusztrátorokat tartalmaz, az albumkészítőket nem. A származtatott osztályban a Művész tulajdonság újradefiniálása megakadályozza, hogy az osztály az alaposztályban található statikus tulajdonságot adja vissza.

Az utolsó kódblokk meghívja a ToString() metódust az alaposztály statikus Lista tulajdonságának bejegyzéseihez.

[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)

A Album példányai csak a saját sztringjükben szereplő nevet és előadót adják vissza. A illusztrációs példányok zárójelben tartalmazták a közeget is, mivel ez az osztály felülírta a ToString() metódust.

2. példa – Interfészek implementálása

Az alábbi példa bemutatja, hogyan valósíthat meg egy osztály egy vagy több felületet. A példa kibővíti a Hőmérséklet osztály definícióját a további műveletek és viselkedések támogatásához.

Kezdeti osztálydefiníció

Bármely felület implementálása előtt a Hőmérséklet osztály két tulajdonsággal van definiálva: Fok és Skála. Konstruktorokat és három példánymetelyt határoz meg a példány adott skálázási fokként való visszaadásához.

Az osztály a TemperatureScale enumerálással határozza meg a rendelkezésre álló skálákat.

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
}

Ebben az alapszintű implementációban azonban van néhány korlátozás az alábbi példakimenetben látható módon:

$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.

A kimenet azt mutatja, hogy a Hőmérsékletpéldányai:

  • Nem jelenik meg helyesen szövegként.
  • Nem ellenőrizhető megfelelően az egyenértékűség.
  • Nem lehet összehasonlítani.

Ez a három probléma megoldható az osztály felületeinek implementálásával.

Az IFormattable implementálása

A Hőmérséklet osztály elsőként implementálandó felülete a System.IFormattable. Ez a felület lehetővé teszi az osztály egy példányának formázását különböző sztringekként. Az interfész implementálásához az osztálynak örökölnie kell System.IFormattable, és meg kell határoznia a ToString() példánymetódusát.

A ToString() példány metódusának a következő aláírásra van szüksége:

[string] ToString(
    [string]$Format,
    [System.IFormatProvider]$FormatProvider
) {
    # Implementation
}

Az interfész által igényelt aláírás szerepel a referenciadokumentációban.

A Hőmérsékletesetében az osztálynak három formátumot kell támogatnia: C a példány Celsiusban való visszaadásához, F a Fahrenheitben való visszaadáshoz, és K a Kelvinben való visszaadáshoz. Bármilyen más formátum esetén a metódusnak System.FormatExceptionkell dobnia.

[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'"
    )
}

Ebben az implementációban a metódus alapértelmezetten az azonosító példány formátumát és az aktuális kultúrát alkalmazza a numerikus fokérték maga formázásakor. A To<Scale>() példánymetódusait használja a fokok konvertálására, formázza két tizedesjegyre, és hozzáfűzi a megfelelő fokszimbólumot a karakterlánchoz.

A szükséges aláírás implementálásával az osztály túlterheléseket is definiálhat, hogy könnyebben visszaadhassa a formázott példányt.

[string] ToString([string]$Format) {
    return $this.ToString($Format, $null)
}

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

Az alábbi kód a Hőmérsékletfrissített definícióját mutatja be:

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
}

A metódus túlterheléseinek kimenete az alábbi blokkban látható.

$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

Az IEquatable implementálása

Most, hogy a Hőmérséklet osztály formázható az olvashatóság érdekében, a felhasználóknak tudniuk kell ellenőrizni, hogy az osztály két példánya egyenlő-e. A teszt támogatásához az osztálynak implementálnia kell a System.IEquatable felületet.

Az interfész implementálásához az osztálynak örökölnie kell System.IEquatable, és meg kell határoznia a Equals() példány metódusát. A Equals() metódusnak a következő aláírásra van szüksége:

[bool] Equals([Object]$Other) {
    # Implementation
}

Az interfész által igényelt aláírás szerepel a referenciadokumentációban.

Hőmérsékletesetében az osztálynak csak az osztály két példányának összehasonlítását kell támogatnia. Bármely más értéknél vagy típusnál, beleértve $null, az $falsekell visszaadnia. Két hőmérséklet összehasonlítása esetén a módszernek mindkét értéket Kelvinre kell konvertálnia, mivel a hőmérsékletek különböző skálákkal is egyenértékűek lehetnek.

[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()
}

Az interfészmetódus implementálásával a Hőmérséklet frissített definíciója a következő:

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
}

Az alábbi blokk a frissített osztály viselkedését mutatja be:

$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

Az IComparable implementálása

A hőmérséklet osztály esetében az utolsó implementálandó felület a System.IComparable. Amikor az osztály implementálja ezt a felületet, a felhasználók a -lt, -le, -gtés -ge operátorokkal összehasonlíthatják az osztály példányait.

Az interfész implementálásához az osztálynak örökölnie kell System.IComparable, és meg kell határoznia a Equals() példány metódusát. A Equals() metódusnak a következő aláírásra van szüksége:

[int] CompareTo([Object]$Other) {
    # Implementation
}

Az interfész által igényelt aláírás szerepel a referenciadokumentációban.

Hőmérsékletesetében az osztálynak csak az osztály két példányának összehasonlítását kell támogatnia. Mivel a Fok tulajdonság mögöttes típusa – még akkor is, ha más skálára konvertálják – lebegőpontos szám, a metódus a tényleges összehasonlítás alapjául szolgáló típusra támaszkodhat.

[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())
}

A Hőmérséklet osztály végső definíciója a következő:

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
}

A teljes definícióval a felhasználók bármilyen beépített típushoz hasonlóan formázhatják és összehasonlíthatják az osztály példányait a PowerShellben.

$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

3. példa – Öröklődés egy általános alaposztályból

Ez a példa bemutatja, hogyan lehet általános típusból származni, ha a típusparaméter már definiálva van elemzési időpontban.

Beépített osztály használata típusparaméterként

Futtassa a következő kódrészletet. Bemutatja, hogyan örökölhet egy új osztály egy általános típustól, ha a típusparaméter már definiálva van elemzési időpontban.

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

Egyéni osztály használata típusparaméterként

A következő kódblokk először egy új osztályt határoz meg, ExampleItem, egyetlen példánytulajdonság és a ToString() metódus használatával. Ezután meghatározza az ExampleItemList osztályt, amely a System.Collections.Generic.List alaposztályból öröklődik, és típusparaméterként ExampleItem.

Másolja ki a teljes kódblokkot, és futtassa egyetlen utasításként.

class ExampleItem {
    [string] $Name
    [string] ToString() { return $this.Name }
}
class ExampleItemList : System.Collections.Generic.List[ExampleItem] {}
ParentContainsErrorRecordException: An error occurred while creating the pipeline.

A teljes kódblokk futtatása hibát jelez, mert a PowerShell még nem töltötte be a ExampleItem osztályt a futtatókörnyezetbe. A System.Collections.Generic.List alaposztályhoz még nem használhat osztálynevet típusparaméterként.

Futtassa a következő kódblokkokat a definiált sorrendben.

class ExampleItem {
    [string] $Name
    [string] ToString() { return $this.Name }
}
class ExampleItemList : System.Collections.Generic.List[ExampleItem] {}

A PowerShell ezúttal nem okoz hibát. Most már mindkét osztály definiálva van. Futtassa az alábbi kódblokkot az új osztály viselkedésének megtekintéséhez.

$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

Általános és egyéni típusparaméter származtatása egy modulban

Az alábbi kódblokkok bemutatják, hogyan definiálhat olyan osztályt, amely öröklődik egy olyan általános alaposztálytól, amely egyéni típust használ a típusparaméterhez.

Mentse a következő kódblokkot GenericExample.psd1.

@{
    RootModule        = 'GenericExample.psm1'
    ModuleVersion     = '0.1.0'
    GUID              = '2779fa60-0b3b-4236-b592-9060c0661ac2'
}

Mentse a következő kódblokkot 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))"
    }
}

Mentse a következő kódblokkot 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()

Tipp

A gyökérmodul hozzáadja az egyéni típusokat a PowerShell típusgyorsítóihoz. Ez a minta lehetővé teszi, hogy a modul felhasználói azonnal hozzáférhessenek az IntelliSense-hez, és automatikusan kitölthessék az egyéni típusokat anélkül, hogy először a using module utasítást kellene használniuk.

Erről a mintáról további információt a about_Classes"Exportálás típusgyorsítókkal" című szakaszában talál.

Importálja a modult, és ellenőrizze a kimenetet.

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

A modul hiba nélkül töltődik be, mert a InventoryItem osztály egy másik modulfájlban van definiálva, mint a Inventory osztály. Mindkét osztály elérhető a modul felhasználói számára.

Alaposztály öröklése

Amikor egy osztály örökli az alaposztályt, az örökli az alaposztály tulajdonságait és metódusait. Nem örökli közvetlenül az alaposztály konstruktorait, de meghívhatja őket.

Ha az alaposztály a PowerShell helyett a .NET-ben van definiálva, vegye figyelembe, hogy:

  • A PowerShell-osztályok nem örökölhetnek lezárt osztályokból.
  • Ha egy általános alaposztálytól örököl, az általános osztály típusparamétere nem lehet származtatott osztály. A származtatott osztály típusparaméterként való használata elemzési hibát okoz.

Ha meg szeretné tudni, hogyan működik az öröklés és a felülírás a származtatott osztályok esetében, tekintse meg 1. példa.

Származtatott osztálykonstruktorok

A származtatott osztályok nem öröklik közvetlenül az alaposztály konstruktorait. Ha az alaposztály alapértelmezett konstruktort határoz meg, és a származtatott osztály nem határoz meg konstruktorokat, a származtatott osztály új példányai az alaposztály alapértelmezett konstruktorát használják. Ha az alaposztály nem definiál alapértelmezett konstruktort, a származtatott osztálynak explicit módon kell definiálnia legalább egy konstruktort.

A származtatott osztálykonstruktorok meghívhatnak egy konstruktort az alaposztályból a base kulcsszóval. Ha a származtatott osztály nem hív meg explicit módon konstruktort az alaposztályból, ehelyett az alaposztály alapértelmezett konstruktorát hívja meg.

Ha nem alapértelmezett alapkonstruktort szeretne meghívni, adja hozzá a : base(<parameters>)-t a konstruktor paraméterei után és a törzsrész előtt.

class <derived-class> : <base-class> {
    <derived-class>(<derived-parameters>) : <base-class>(<base-parameters>) {
        # initialization code
    }
}

Alaposztály-konstruktort meghívó konstruktor definiálásakor a paraméterek a következő elemek bármelyikét tartalmazhatják:

  • A származtatott osztálykonstruktor bármely paraméterének változója.
  • Bármilyen statikus érték.
  • Bármely kifejezés, amely a paramétertípus értékére értékelhető ki.

Az 1. példa Illusztráció osztálya bemutatja, hogyan használhatja egy származtatott osztály az alaposztály konstruktorokat.

Származtatott osztály metódusai

Amikor egy osztály egy alaposztályból származik, örökli az alaposztály metódusait és azok túlterheléseit. Az alaposztályon definiált metódusterhelések, beleértve a rejtett metódusokat is, elérhetők a származtatott osztályban.

A származtatott osztályok felülbírálhatják az örökölt metódusok túlterhelését, ha újradefiniálják azt az osztálydefinícióban. A túlterhelés felülbírálásához a paramétertípusoknak meg kell egyeznie az alaposztály típusával. A túlterhelés kimeneti típusa eltérő lehet.

A konstruktoroktól eltérően a metódusok nem használhatják a : base(<parameters>) szintaxist a metódus alaposztály-túlterhelésének meghívásához. A származtatott osztály újradefiniált túlterhelése teljesen felülírja az alaposztály által definiált túlterhelést. Egy példány alaposztály-metódusának meghívásához a metódus meghívása előtt a példányváltozót ($this) az alaposztályhoz kell adni.

Az alábbi kódrészlet bemutatja, hogyan hívhatja meg egy származtatott osztály az alaposztály metódusát.

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

Az örökölt metódusok felülbírálásának módját bemutató bővített mintaért tekintse meg az Ábra osztályt az 1. példa.

Származtatott osztálytulajdonságok

Amikor egy osztály egy alaposztályból származik, az örökli az alaposztály tulajdonságait. Az alaposztályon definiált tulajdonságok, beleértve a rejtett tulajdonságokat is, elérhetők a származtatott osztályban.

A származtatott osztályok felülbírálhatnak egy örökölt tulajdonságot, ha újradefiniálják azt az osztálydefinícióban. A származtatott osztály tulajdonsága az újradefiniált típust és az alapértelmezett értéket használja, ha van ilyen. Ha az örökölt tulajdonság alapértelmezett értéket definiált, és az újradefiniált tulajdonság nem, az örökölt tulajdonság nem rendelkezik alapértelmezett értékkel.

Ha egy származtatott osztály nem felülbírál egy statikus tulajdonságot, a származtatott osztályon keresztül elért statikus tulajdonság az alaposztály statikus tulajdonságához fér hozzá. A tulajdonságérték származtatott osztályon keresztül történő módosítása módosítja az alaposztály értékét. Minden más származtatott osztály, amely nem bírálja felül a statikus tulajdonságot, az alaposztály tulajdonságának értékét is használja. Az örökölt statikus tulajdonság értékének frissítése olyan osztályban, amely nem bírálja felül a tulajdonságot, előfordulhat, hogy az azonos alaposztályból származó osztályokra nem tervezett hatással van.

1. példa bemutatja, hogyan öröklik, bővítik és felülbírálják az alaposztály tulajdonságait a származtatott osztályok.

Származtatás generikus típusokból

Ha egy osztály egy általános osztályból származik, a típusparamétert már meg kell határozni, mielőtt a PowerShell elemzi a származtatott osztályt. Ha az általános típusparaméter ugyanabban a fájlban vagy kódblokkban definiált PowerShell-osztály vagy felsorolás, a PowerShell hibát jelez.

Ha egy egyéni típussal rendelkező általános alaposztályból szeretne osztályt származtatni, adja meg a típusparaméter osztályát vagy enumerálását egy másik fájlban vagy modulban, és használja a using module utasítást a típusdefiníció betöltéséhez.

A generikus alaposztályból való öröklődést bemutató példát lásd a Példa 3részben.

Hasznos örökölendő osztályok

Néhány osztály hasznos lehet a PowerShell-modulok létrehozásakor. Ez a szakasz felsorol néhány alaposztályt, és azt, hogy az ezekből származtatott osztály mire használható.

  • System.Attribute – A változókhoz, paraméterekhez, osztály- és számbavételi definíciókhoz használható attribútumok definiálásához osztályokat hozhat létre.
  • System.Management.Automation.ArgumentTransformationAttribute – Osztályokat hozhat létre egy változó vagy paraméter bemenetének adott adattípussá alakításához.
  • System.Management.Automation.ValidateArgumentsAttribute – Az osztályok származtatásával egyéni ellenőrzést alkalmazhat változókra, paraméterekre és osztálytulajdonságokra.
  • System.Collections.Generic.List – Osztályokat származtathat egy adott adattípusú listák létrehozásához és kezeléséhez.
  • System.Exception – Egyéni hibák definiálásához osztályokat kell származtatnia.

Interfészek implementálása

Az interfészt megvalósító PowerShell-osztálynak implementálnia kell a felület összes tagját. Ha kihagyja a megvalósítási felület tagjait, az elemzési időt jelző hibát okoz a szkriptben.

Jegyzet

A PowerShell nem támogatja az új felületek deklarálását a PowerShell-szkriptben. Ehelyett a felületeket .NET-kódban kell deklarálni, és hozzá kell adni a munkamenethez a Add-Type parancsmaggal vagy a using assembly utasítással.

Amikor egy osztály implementál egy interfészt, az bármely más, az adott felületet megvalósító osztályhoz hasonlóan használható. Egyes parancsok és műveletek a támogatott típusokat egy adott interfészt megvalósító osztályokra korlátozzák.

Az interfészek mintaalkalmazásának áttekintéséhez lásd 2. példa.

Hasznos felületek implementálásához

A PowerShell-modulok létrehozásakor néhány felületosztály hasznos lehet. Ez a szakasz felsorol néhány alaposztályt, és azt, hogy az ezekből származtatott osztály mire használható.

  • System.IEquatable – Ezzel a felülettel a felhasználók összehasonlíthatják az osztály két példányát. Ha egy osztály nem implementálja ezt a felületet, a PowerShell a hivatkozási egyenlőség használatával ellenőrzi a két példány közötti egyenértékűséget. Más szóval az osztály egy példánya csak önmagával egyenlő, még akkor is, ha két példány tulajdonságértéke megegyezik.
  • System.IComparable – Ezzel a felülettel a felhasználók összehasonlíthatják az osztály példányait az -le, -lt, -geés -gt összehasonlító operátorokkal. Ha egy osztály nem implementálja ezt a felületet, ezek az operátorok hibát jeleznek.
  • System.IFormattable – Ezzel a felülettel a felhasználók különböző sztringekké formázhatják az osztály példányait. Ez olyan osztályok esetében hasznos, amelyek több standard sztringet ábrázolnak, például költségvetési elemeket, irodalomjegyzékeket és hőmérsékleteket.
  • System.IConvertible – Ez a felület lehetővé teszi a felhasználók számára, hogy az osztály példányait más futtatókörnyezet-típusokra konvertálják. Ez az alapul szolgáló numerikus értékkel rendelkező vagy átalakítható osztályok esetében hasznos.

Korlátozások

  • A PowerShell nem támogatja a szkriptkódban lévő interfészek meghatározását.

    Kerülő megoldás: Definiálja a C# interfészeket, és hivatkozzon az ezeket definiáló assemblyre.

  • A PowerShell-osztályok csak egy alaposztályból örökölhetnek.

    Megkerülő megoldás: Az osztályöröklés tranzitív. A származtatott osztály örökölhet egy másik származtatott osztálytól, hogy lekérje az alaposztály tulajdonságait és metódusait.

  • Ha általános osztályból vagy interfészből örököl, az általános típusparamétert már meg kell határozni. Az osztály nem definiálhatja magát egy osztály vagy felület típusparamétereként.

    Megkerülő megoldás: Ha általános alaposztályból vagy felületről szeretne származni, adja meg az egyéni típust egy másik .psm1 fájlban, és használja a using module utasítást a típus betöltéséhez. Nincs áthidaló megoldás arra, hogy egy egyéni típus típusparaméterként használja magát az általánostól való öröklődéskor.

Lásd még