Delen via


about_Classes_Constructors

Korte beschrijving

Hierin wordt beschreven hoe u constructors voor PowerShell-klassen definieert.

Lange beschrijving

Met constructors kunt u standaardwaarden instellen en objectlogica valideren op het moment dat het exemplaar van de klasse wordt gemaakt. Constructors hebben dezelfde naam als de klasse. Constructors kunnen parameters hebben om de gegevensleden van het nieuwe object te initialiseren.

PowerShell-klasseconstructors worden gedefinieerd als speciale methoden voor de klasse. Ze gedragen zich hetzelfde als PowerShell-klassemethoden, met de volgende uitzonderingen:

  • Constructors hebben geen uitvoertype. Ze kunnen het return trefwoord niet gebruiken.
  • Constructors hebben altijd dezelfde naam als de klasse.
  • Constructors kunnen niet rechtstreeks worden aangeroepen. Ze worden alleen uitgevoerd wanneer een exemplaar wordt gemaakt.
  • Constructors worden nooit weergegeven in de uitvoer voor de Get-Member cmdlet.

Zie about_Classes_Methods voor meer informatie over PowerShell-klassenmethoden.

Voor de klasse kunnen nul of meer constructors zijn gedefinieerd. Als er geen constructor is gedefinieerd, krijgt de klasse een standaardconstructor zonder parameter. Deze constructor initialiseert alle leden naar hun standaardwaarden. Objecttypen en tekenreeksen krijgen null-waarden. Wanneer u de constructor definieert, wordt er geen standaardconstructor zonder parameter gemaakt. Creatie indien nodig een constructor zonder parameters.

U kunt ook een statische constructor zonder parameters definiëren.

Syntax

Klasseconstructors gebruiken de volgende syntaxis:

Standaardconstructorsyntaxis

<class-name> () [: base([<params>])] {
    <body>
}

Statische constructorsyntaxis

static <class-name> () [: base([<params>])] {
    <body>
}

Geparameteriseerde constructorsyntaxis (één regel)

<class-name> ([[<parameter-type>]$<parameter-name>[, [<parameter-type>]$<parameter-name>...]]) [: base([<params>])] {
    <body>
}

Geparameteriseerde constructorsyntaxis (meerdere regels)

<class-name> (
    [<parameter-type>]$<parameter-name>[,
    [<parameter-type>]$<parameter-name>...]
) [: base([<params>])] {
    <body>
}

Voorbeelden

Voorbeeld 1: een klasse definiëren met de standaardconstructor

De klasse ExampleBook1 definieert geen constructor. In plaats daarvan wordt de automatische standaardconstructor gebruikt.

class ExampleBook1 {
    [string]   $Name
    [string]   $Author
    [int]      $Pages
    [datetime] $PublishedOn
}

[ExampleBook1]::new()
Name Author Pages PublishedOn
---- ------ ----- -----------
                0 1/1/0001 12:00:00 AM

Notitie

De standaardwaarde voor de eigenschappen Naam en Auteur is $null omdat ze zijn getypt als tekenreeksen. Dit is een verwijzingstype. De andere eigenschappen hebben de standaardwaarde voor het gedefinieerde type, omdat het eigenschappen van het waardetype zijn. Zie 'Standaardeigenschapswaarden' in about_Classes_Properties voor meer informatie over de standaardwaarden voor eigenschappen.

Voorbeeld 2: de standaardconstructor overschrijven

ExampleBook2 definieert expliciet de standaardconstructor, waarbij de waarden voor PublishedOn worden ingesteld op de huidige datum en Pagina's op 1.

class ExampleBook2 {
    [string]   $Name
    [string]   $Author
    [int]      $Pages
    [datetime] $PublishedOn

    ExampleBook2() {
        $this.PublishedOn = (Get-Date).Date
        $this.Pages       = 1
    }
}

[ExampleBook2]::new()
Name Author Pages PublishedOn
---- ------ ----- -----------
                1 11/1/2023 12:00:00 AM

Voorbeeld 3: overbelasting van constructor definiëren

De klasse ExampleBook3 definieert drie constructor-overloads, waardoor gebruikers een exemplaar van de klasse kunnen maken op basis van een hashtabel, door elke eigenschapswaarde door te geven en door de naam van het boek en de auteur door te geven. De klasse definieert de standaardconstructor niet.

class ExampleBook3 {
    [string]   $Name
    [string]   $Author
    [int]      $Pages
    [datetime] $PublishedOn

    ExampleBook3([hashtable]$Info) {
        switch ($Info.Keys) {
            'Name'        { $this.Name        = $Info.Name }
            'Author'      { $this.Author      = $Info.Author }
            'Pages'       { $this.Pages       = $Info.Pages }
            'PublishedOn' { $this.PublishedOn = $Info.PublishedOn }
        }
    }

    ExampleBook3(
        [string]   $Name,
        [string]   $Author,
        [int]      $Pages,
        [datetime] $PublishedOn
    ) {
        $this.Name        = $Name
        $this.Author      = $Author
        $this.Pages       = $Pages
        $this.PublishedOn = $PublishedOn
    }

    ExampleBook3([string]$Name, [string]$Author) {
        $this.Name   = $Name
        $this.Author = $Author
    }
}

[ExampleBook3]::new(@{
    Name        = 'The Hobbit'
    Author      = 'J.R.R. Tolkien'
    Pages       = 310
    PublishedOn = '1937-09-21'
})
[ExampleBook3]::new('The Hobbit', 'J.R.R. Tolkien', 310, '1937-09-21')
[ExampleBook3]::new('The Hobbit', 'J.R.R. Tolkien')
[ExampleBook3]::new()
Name       Author         Pages PublishedOn
----       ------         ----- -----------
The Hobbit J.R.R. Tolkien   310 9/21/1937 12:00:00 AM
The Hobbit J.R.R. Tolkien   310 9/21/1937 12:00:00 AM
The Hobbit J.R.R. Tolkien     0 1/1/0001 12:00:00 AM

MethodException:
Line |
  42 |  [ExampleBook3]::new()
     |  ~~~~~~~~~~~~~~~~~~~~~
     | Cannot find an overload for "new" and the argument count: "0".

Als u de standaardconstructor aanroept, wordt een methode-uitzondering geretourneerd. De automatische standaardconstructor wordt alleen gedefinieerd voor een klasse wanneer de klasse geen constructors definieert. Omdat ExampleBook3 meerdere overloads definieert, wordt de standaardconstructor niet automatisch toegevoegd aan de klasse.

Voorbeeld 4: constructors koppelen met een gedeelde methode

In dit voorbeeld ziet u hoe u herbruikbare gedeelde code voor constructors kunt schrijven. PowerShell-klassen kunnen geen gebruik maken van constructorkoppeling, dus in deze voorbeeldklasse wordt in plaats daarvan een Init() methode gedefinieerd. De methode heeft verschillende overbelastingen. De overloads met minder parameters roepen de meer expliciete overloads aan met standaardwaarden voor de niet-opgegeven parameters.

class ExampleBook4 {
    [string]   $Name
    [string]   $Author
    [datetime] $PublishedOn
    [int]      $Pages

    ExampleBook4() {
        $this.Init()
    }
    ExampleBook4([string]$Name) {
        $this.Init($Name)
    }
    ExampleBook4([string]$Name, [string]$Author) {
        $this.Init($Name, $Author)
    }
    ExampleBook4([string]$Name, [string]$Author, [datetime]$PublishedOn) {
        $this.Init($Name, $Author, $PublishedOn)
    }
    ExampleBook4(
      [string]$Name,
      [string]$Author,
      [datetime]$PublishedOn,
      [int]$Pages
    ) {
        $this.Init($Name, $Author, $PublishedOn, $Pages)
    }

    hidden Init() {
        $this.Init('Unknown')
    }
    hidden Init([string]$Name) {
        $this.Init($Name, 'Unknown')
    }
    hidden Init([string]$Name, [string]$Author) {
        $this.Init($Name, $Author, (Get-Date).Date)
    }
    hidden Init([string]$Name, [string]$Author, [datetime]$PublishedOn) {
        $this.Init($Name, $Author, $PublishedOn, 1)
    }
    hidden Init(
        [string]$Name,
        [string]$Author,
        [datetime]$PublishedOn,
        [int]$Pages
      ) {
        $this.Name        = $Name
        $this.Author      = $Author
        $this.PublishedOn = $PublishedOn
        $this.Pages       = $Pages
    }
}

[ExampleBook4]::new()
[ExampleBook4]::new('The Hobbit')
[ExampleBook4]::new('The Hobbit', 'J.R.R. Tolkien')
[ExampleBook4]::new('The Hobbit', 'J.R.R. Tolkien', (Get-Date '1937-9-21'))
[ExampleBook4]::new(
    'The Hobbit',
    'J.R.R. Tolkien',
    (Get-Date '1937-9-21'),
    310
)
Name       Author         PublishedOn           Pages
----       ------         -----------           -----
Unknown    Unknown        11/1/2023 12:00:00 AM     1
The Hobbit Unknown        11/1/2023 12:00:00 AM     1
The Hobbit J.R.R. Tolkien 11/1/2023 12:00:00 AM     1
The Hobbit J.R.R. Tolkien 9/21/1937 12:00:00 AM     1
The Hobbit J.R.R. Tolkien 9/21/1937 12:00:00 AM   310

Voorbeeld 5: Afgeleide klasseconstructors

In de volgende voorbeelden worden klassen gebruikt die de statische, standaardconstructors en geparameteriseerde constructors definiëren voor een basisklasse en een afgeleide klasse die wordt overgenomen van de basisklasse.

class BaseExample {
    static [void] DefaultMessage([type]$Type) {
        Write-Verbose "[$($Type.Name)] default constructor"
    }

    static [void] StaticMessage([type]$Type) {
        Write-Verbose "[$($Type.Name)] static constructor"
    }

    static [void] ParamMessage([type]$Type, [object]$Value) {
        Write-Verbose "[$($Type.Name)] param constructor ($Value)"
    }

    static BaseExample() { [BaseExample]::StaticMessage([BaseExample])  }
    BaseExample()        { [BaseExample]::DefaultMessage([BaseExample]) }
    BaseExample($Value)  { [BaseExample]::ParamMessage([BaseExample], $Value) }
}

class DerivedExample : BaseExample {
    static DerivedExample() { [BaseExample]::StaticMessage([DerivedExample])  }
           DerivedExample() { [BaseExample]::DefaultMessage([DerivedExample]) }

    DerivedExample([int]$Number) : base($Number) {
        [BaseExample]::ParamMessage([DerivedExample], $Number)
    }
    DerivedExample([string]$String) {
        [BaseExample]::ParamMessage([DerivedExample], $String)
    }
}

In het volgende blok ziet u de uitgebreide berichten voor het aanroepen van de basisklasseconstructors. Het statische constructorbericht wordt alleen verzonden wanneer er voor het eerst een exemplaar van de klasse wordt gemaakt.

PS> $VerbosePreference = 'Continue'
PS> $b = [BaseExample]::new()

VERBOSE: [BaseExample] static constructor
VERBOSE: [BaseExample] default constructor

PS> $b = [BaseExample]::new()

VERBOSE: [BaseExample] default constructor

PS> $b = [BaseExample]::new(1)

VERBOSE: [BaseExample] param constructor (1)

In het volgende blok ziet u de uitgebreide berichten voor het aanroepen van de afgeleide klasseconstructors in een nieuwe sessie. De eerste keer dat een afgeleide klasseconstructor wordt aangeroepen, worden de statische constructors voor de basisklasse en afgeleide klasse aangeroepen. Deze constructors worden niet opnieuw aangeroepen in de sessie. De constructors voor de basisklasse worden altijd uitgevoerd vóór de constructors voor de afgeleide klasse.

PS> $VerbosePreference = 'Continue'
PS> $c = [DerivedExample]::new()

VERBOSE: [BaseExample] static constructor
VERBOSE: [DerivedExample] static constructor
VERBOSE: [BaseExample] default constructor
VERBOSE: [DerivedExample] default constructor

PS> $c = [DerivedExample]::new()

VERBOSE: [BaseExample] default constructor
VERBOSE: [DerivedExample] default constructor

PS> $c = [DerivedExample]::new(1)

VERBOSE: [BaseExample] param constructor (1)
VERBOSE: [DerivedExample] param constructor (1)

PS> $c = [DerivedExample]::new('foo')

VERBOSE: [BaseExample] default constructor
VERBOSE: [DerivedExample] param constructor (foo)

Volgorde van uitvoering van constructor

Wanneer een klasse een instantie maakt, wordt de code voor een of meer constructors uitgevoerd.

Voor klassen die niet overnemen van een andere klasse, is de volgorde:

  1. De statische constructor voor de klasse.
  2. De toepasselijke constructoroverbelasting voor de klasse.

Voor afgeleide klassen die overnemen van een andere klasse, is de volgorde:

  1. De statische constructor voor de basisklasse.
  2. De statische constructor voor de afgeleide klasse.
  3. Als de afgeleide klasseconstructor expliciet een overbelasting van de basisconstructor aanroept, wordt die constructor uitgevoerd voor de basisklasse. Als er niet expliciet een basisconstructor wordt aangeroepen, wordt de standaardconstructor voor de basisklasse uitgevoerd.
  4. De toepasselijke constructoroverbelasting voor de afgeleide klasse.

In alle gevallen worden statische constructors slechts eenmaal in een sessie uitgevoerd.

Zie voorbeeld 5 voor een voorbeeld van het gedrag en de volgorde van de constructor.

Verborgen constructors

U kunt constructors van een klasse verbergen door deze te declareren met het hidden trefwoord. Verborgen klasseconstructors zijn:

  • Niet opgenomen in de standaarduitvoer voor de klasse.
  • Niet opgenomen in de lijst met klasseleden die door de Get-Member cmdlet worden geretourneerd. Als u verborgen eigenschappen wilt weergeven met Get-Member, gebruikt u de parameter Force .
  • Wordt niet weergegeven in tabvoltooiing of IntelliSense, tenzij de voltooiing plaatsvindt in de klasse die de verborgen eigenschap definieert.
  • Openbare leden van de klasse. Ze kunnen worden geopend en gewijzigd. Als u een eigenschap verbergt, wordt deze niet privé. Alleen de eigenschap wordt verborgen zoals beschreven in de vorige punten.

Notitie

Wanneer u een constructor verbergt, wordt de new() optie verwijderd uit IntelliSense en voltooiingsresultaten.

Zie about_Hidden voor meer informatie over het hidden trefwoord.

Statische constructors

U kunt een constructor definiëren als behorend tot de klasse zelf in plaats van exemplaren van de klasse door de constructor te declareren met het static trefwoord. Statische klasseconstructors:

  • Roep alleen de eerste keer aan dat een exemplaar van de klasse wordt gemaakt in de sessie.
  • Kan geen parameters hebben.
  • Kan geen toegang krijgen tot exemplaareigenschappen of -methoden met de $this variabele.

Constructors voor afgeleide klassen

Wanneer een klasse wordt overgenomen van een andere klasse, kunnen constructors een constructor van de basisklasse aanroepen met het base trefwoord. Als de afgeleide klasse niet expliciet een constructor aanroept van de basisklasse, wordt in plaats daarvan de standaardconstructor voor de basisklasse aangeroepen.

Als u een niet-standaardbasisconstructor wilt aanroepen, voegt u toe : base(<parameters>) na de constructorparameters en vóór het hoofdtekstblok.

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

Bij het definiëren van een constructor die een basisklasseconstructor aanroept, kunnen de parameters een van de volgende items zijn:

  • De variabele van een parameter op de afgeleide klasseconstructor.
  • Een statische waarde.
  • Een expressie die resulteert in een waarde van het parametertype.

Zie voorbeeld 5 voor een voorbeeld van constructors op een afgeleide klasse.

Ketenconstructors

In tegenstelling tot C# kunnen PowerShell-klasseconstructors geen gebruik maken van ketens met de : this(<parameters>) syntaxis. Als u codeduplicatie wilt verminderen, gebruikt u een verborgen Init() methode met meerdere overbelastingen met hetzelfde effect. In voorbeeld 4 ziet u een klasse met dit patroon.

Exemplaareigenschappen en -methoden toevoegen met Update-TypeData

Naast het rechtstreeks declareren van eigenschappen en methoden in de klassedefinitie, kunt u eigenschappen definiëren voor exemplaren van een klasse in de statische constructor met behulp van de Update-TypeData cmdlet.

Gebruik dit codefragment als beginpunt voor het patroon. Vervang indien nodig de tekst van de tijdelijke aanduiding tussen punthaken.

class <class-name> {
    static [hashtable[]] $MemberDefinitions = @(
        @{
            Name       = '<member-name>'
            MemberType = '<member-type>'
            Value      = <member-definition>
        }
    )

    static <class-name>() {
        $TypeName = [<class-name>].Name
        foreach ($Definition in [<class-name>]::MemberDefinitions) {
            Update-TypeData -TypeName $TypeName @Definition
        }
    }
}

Tip

De Add-Member cmdlet kan eigenschappen en methoden toevoegen aan een klasse in niet-statische constructors, maar de cmdlet wordt elke keer uitgevoerd wanneer de constructor wordt aangeroepen. Als Update-TypeData u in de statische constructor gebruikt, zorgt u ervoor dat de code voor het toevoegen van de leden aan de klasse slechts eenmaal in een sessie hoeft te worden uitgevoerd.

Voeg alleen eigenschappen toe aan de klasse in niet-statische constructors wanneer deze niet kunnen worden gedefinieerd met Update-TypeData, zoals alleen-lezeneigenschappen.

Zie about_Classes_Methods voor meer informatie over het definiëren van exemplaarmethoden metUpdate-TypeData. Zie about_Classes_Properties voor meer informatie over het definiëren van exemplaareigenschappen metUpdate-TypeData.

Beperkingen

PowerShell-klasseconstructors hebben de volgende beperkingen:

  • Constructorkoppeling is niet geïmplementeerd.

    Tijdelijke oplossing: definieer verborgen Init() methoden en roep deze aan vanuit de constructors.

  • Constructorparameters kunnen geen kenmerken gebruiken, inclusief validatiekenmerken.

    Tijdelijke oplossing: wijs de parameters in de constructorbody opnieuw toe met het validatiekenmerk.

  • Constructorparameters kunnen geen standaardwaarden definiëren. De parameters zijn altijd verplicht.

    Tijdelijke oplossing: geen.

  • Als een overbelasting van een constructor verborgen is, wordt elke overbelasting voor de constructor ook als verborgen behandeld.

    Tijdelijke oplossing: geen.

Zie ook