about_Classes_Inheritance

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 az öröklést, így meghatározhat egy gyermekosztályt, 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 tagjai öröklődnek, alaposztálynak nevezzük. Az alaposztály tagjait öröklő osztályt származtatott osztálynak nevezzü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 típus a C típustól örökölhet, amely a B típustól öröklődik, amely az A alaposztály típusától öröklődik. Mivel az öröklés tranzitív, az A típusú tagok a D típushoz érhetők el.

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 igen, az osztály használható, mint bármely más osztály 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. Az operátor például csak akkor ellenőrzi a -eq referenciaegyenlőséget, ha az osztály nem implementálja a System.IEquatable interfészt . A -le, -lt, -geés -gt operátorok csak a System.IComparable felületet megvalósító osztályokon működnek.

A származtatott osztály a szintaxist használja egy : alaposztály kibővítésére vagy interfészek implementálására. 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 {...}

Syntax

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élda:

# 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élda:

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 alaposztályként definiálja a PublishedWorket . Két statikus tulajdonsággal rendelkezik, a List és az Artists tulajdonsággal. Ezután meghatározza a statikus RegisterWork() metódust, amely műveket ad hozzá a statikus Lista tulajdonsághoz és a művészeket az Artists 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 az és ToString() a Register() 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 az Album. Nem bírál felül tulajdonságokat vagy metódusokat. Hozzáad egy új, műfajok nevű példánytulajdonságot, 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 beállítást, hogy az osztály metódusaiból származó üzenetek a konzolra küldjenek. 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() módszerrel. 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 az Album osztály nem definiált értéket a 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 metódus második hívása RegisterWork() arról számol be, hogy a művek és a művészek már regisztrálva vannak. Annak ellenére, hogy RegisterWork() az első hívás a származtatott Album osztályhoz készült, az alapSzintű PublishedWork osztály örökölt statikus metódusát használta. Ez a módszer frissítette az alaposztály statikus Lista és Művész tulajdonságát, amelyet a származtatott osztály nem bírált felül.

A következő kódblokk törli a beállításjegyzéket, és meghívja a Register() példánymetódust az 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 PublishedWork alaposztálytól öröklő Illusztráció osztályt határozza meg. Az új osztály a Közepes példány tulajdonság alapértelmezett értékével bővíti az alaposztálytUnknown.

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

  • Felülbírálja a statikus Művészek tulajdonságot. A definíció ugyanaz, de az Ábra osztály közvetlenül deklarálja.
  • Felülbírálja a Category instance tulajdonságot, és az alapértelmezett értéket a következőre Illustrationsállítja: .
  • Felülbírálja a ToString() példánymetódust, így az ábrák sztring-ábrázolása tartalmazza a létrehozott adathordozót.

Az osztály meghatározza azt a statikus RegisterIllustration() metódust is, 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 Artists statikus 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 az Előadó tulajdonságainak beállítására szolgáló logika implementálása 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() módszerrel. 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 üzenetkezelése 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 a explicit módon öröklő konstruktor az alaposztályhoz lett meghívva a származtatott osztálykonstruktor 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 módszer részletes üzenetei RegisterWork() 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 nevezte el a RegisterWork() metódust.

Ha azonban az alaposztály és a származtatott osztály statikus Művész tulajdonságának értékét is összehasonlítja, az értékek eltérőek. A származtatott osztály Művész tulajdonsága csak illusztrátorokat tartalmaz, az albumkészítőket nem. A származtatott osztály Művész tulajdonságának újradefiniálása megakadályozza, hogy az osztály visszaadja a statikus tulajdonságot az alaposztályon.

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)

Az albumpéldányok csak a sztringben szereplő nevet és előadót adják vissza. Az illusztrációs példányok zárójelben is tartalmazzák a közepes értéket, mivel ez az osztály felülírja a metódust ToString() .

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ó

Az interfészek implementálása előtt a Hőmérséklet osztály két tulajdonsággal van definiálva: Fok és Skálázás. 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éklet példányai:

  • Nem jelenik meg helyesen sztringké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ő 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 a System.IFormattable-tól kell örökölnie, és meg kell határoznia a ToString() példánymetódust.

A ToString() példánymetódusnak a következő aláírást kell tartalmaznia:

[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éklet esetében az osztálynak három formátumot kell támogatnia: C a példány Visszaadása Celsiusban, F a Fahrenheitben való visszaadása és K a Kelvinben való visszaadása. Bármely más formátum esetén a metódusnak system.FormatException metódust kell használnia.

[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értelmezés szerint a formátum és az aktuális kultúra példánymérete lesz, amikor magát a numerikus fokértéket formázza. A példány metódusával To<Scale>() konvertálja a fokokat, két tizedesjegyre formázza őket, és hozzáfűzi a megfelelő fokszimbólumot a sztringhez.

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éklet frissí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 a System.IEquatable-tól kell örökölnie, és meg kell határoznia a Equals() példánymetódust. A Equals() metódusnak a következő aláírást kell tartalmaznia:

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

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

Hőmérséklet esetén az osztály csak az osztály két példányának összehasonlítását támogatja. Bármely más értékhez vagy típushoz, beleértve a $nullkövetkezőt is, a függvénynek kell visszaadnia $false. 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 utolsó implementálandó felülete 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.

A felület implementálásához az osztálynak a System.IComparable-től kell örökölnie, és meg kell határoznia a Equals() példánymetódust. A Equals() metódusnak a következő aláírást kell tartalmaznia:

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

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

Hőmérséklet esetén az osztály csak az osztály két példányának összehasonlítását támogatja. Mivel a Fok tulajdonság mögöttes típusa , még akkor is, ha egy másik skálára van konvertálva, 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 származhat egy olyan általános osztályból, mint a System.Collections.Generic.List.

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

Futtassa a következő kódblokkot. 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, ExampleItem nevű osztályt határoz meg egyetlen példánytulajdonság és metódus ToString() használatával. Ezután meghatározza a System.Collections.Generic.List alaposztálytól öröklő ExampleItemList osztályt, típusparaméterként pedig az ExampleItem osztályt.

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 az ExampleItem osztályt a futtatókörnyezetbe. A System.Collections.Generic.List alaposztály típusparamétereként még nem használhat osztálynevet.

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 modulfelhasználók azonnal hozzáférjenek az IntelliSense-hez, és automatikusan kitölthessék az egyéni típusokat anélkül, hogy először az 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 az InventoryItem osztály egy másik modulfájlban van definiálva, mint az 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 konstruktorokat, 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.

A származtatott osztályok öröklésének és felülírásának működését az 1. példában tekinthet meg.

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.

Nem hibás alapkonstruktor meghívásához adja hozzá : base(<parameters>) a konstruktor paramétereit és a törzsblokkot.

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ének kiértékelése.

Az 1. példában látható Ábra osztály bemutatja, hogy egy származtatott osztály hogyan használhatja 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 konstruktorokkal ellentétben a metódusok nem használhatják a szintaxist a : base(<parameters>) metódus alaposztály-túlterhelésének meghívására. 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ó kiterjesztett minta az 1. példában található Ábra osztályban található.

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.

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

Származtatás általánosakbó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ájl- vagy kódblokkban definiált PowerShell-osztály vagy számbavétel, a PowerShell hibát jelez.

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

Egy általános alaposztálytól való öröklődést bemutató példát a 3. példában talál.

Örökölendő hasznos 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 – Osztályok levezetése változókhoz, paraméterekhez, osztály- és számbavételi definíciókhoz stb. használható attribútumok definiálásához.
  • System.Management.Automation.ArgumentTransformationAttribute – Osztályok levezetése egy változó vagy paraméter bemenetének adott adattípussá alakításához.
  • System.Management.Automation.ValidateArgumentsAttribute – Az egyéni ellenőrzés változókra, paraméterekre és osztálytulajdonságokra való alkalmazásához használjon osztályokat.
  • System.Collections.Generic.List – Osztályokat származtathat egy adott adattípusú listák létrehozásához és kezeléséhez.
  • System.Exception – Osztályok levezetése egyéni hibák definiálásához.

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.

Feljegyzés

A PowerShell nem támogatja az új felületek deklarálását a PowerShell-szkriptben. Ehelyett az illesztőket .NET-kódban kell deklarálni, és hozzá kell adni a munkamenethez a Add-Type parancsmaggal vagy az 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 minta implementációjának áttekintéséhez lásd a 2. példát.

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 – Ez a felület lehetővé teszi, hogy a felhasználók összehasonlítsák az osztály példányait a -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 – Ez a felület lehetővé teszi a felhasználók számára, hogy az osztály példányait különböző sztringekké formázza. 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, hogy a felhasználók 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.

    Megkerülő megoldás: Adja meg a C# felületeit, és hivatkozzon az illesztőket meghatározó szerelvényre.

  • 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ületből szeretne származni, adja meg az egyéni típust egy másik .psm1 fájlban, és az using module utasítással töltse be a típust. 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.

Kapcsolódó információk