about_Classes_Constructors

Description courte

Décrit comment définir des constructeurs pour les classes PowerShell.

Description longue

Les constructeurs vous permettent de définir des valeurs par défaut et de valider la logique d’objet au moment de la création de l’instance de la classe. Les constructeurs ont le même nom que la classe. Les constructeurs peuvent avoir des paramètres pour initialiser les membres de données du nouvel objet.

Les constructeurs de classe PowerShell sont définis en tant que méthodes spéciales sur la classe. Ils se comportent de la même façon que les méthodes de classe PowerShell avec les exceptions suivantes :

  • Les constructeurs n’ont pas de type de sortie. Ils ne peuvent pas utiliser le return mot clé.
  • Les constructeurs ont toujours le même nom que la classe.
  • Les constructeurs ne peuvent pas être appelés directement. Ils s’exécutent uniquement lorsqu’une instance est créée.
  • Les constructeurs n’apparaissent jamais dans la sortie de l’applet de Get-Member commande.

Pour plus d’informations sur les méthodes de classe PowerShell, consultez about_Classes_Methods.

La classe peut avoir zéro ou plusieurs constructeurs définis. Si aucun constructeur n’est défini, la classe reçoit un constructeur sans paramètre par défaut. Ce constructeur initialise tous les membres à leurs valeurs par défaut. Les types d’objets et les chaînes reçoivent des valeurs Null. Lorsque vous définissez le constructeur, aucun constructeur sans paramètre par défaut n’est créé. Créez un constructeur sans paramètre si nécessaire.

Vous pouvez également définir un constructeur statique sans paramètre.

Syntaxe

Les constructeurs de classes utilisent les syntaxes suivantes :

Syntaxe du constructeur par défaut

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

Syntaxe du constructeur statique

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

Syntaxe de constructeur paramétrable (une ligne)

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

Syntaxe de constructeur paramétrable (multiligne)

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

Exemples

Exemple 1 : Définition d’une classe avec le constructeur par défaut

La classe ExampleBook1 ne définit pas de constructeur. Au lieu de cela, il utilise le constructeur automatique par défaut.

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

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

Remarque

La valeur par défaut des propriétés Name et Author est $null due au fait qu’elles sont typées sous forme de chaînes, qui est un type de référence. Les autres propriétés ont la valeur par défaut pour leur type défini, car elles sont des propriétés de type valeur. Pour plus d’informations sur les valeurs par défaut des propriétés, consultez « Valeurs de propriété par défaut » dans about_Classes_Properties.

Exemple 2 : substitution du constructeur par défaut

ExampleBook2 définit explicitement le constructeur par défaut, en définissant les valeurs de PublishedOn sur la date actuelle et les pages 1 sur .

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

Exemple 3 : Définition des surcharges de constructeur

La classe ExampleBook3 définit trois surcharges de constructeur, ce qui permet aux utilisateurs de créer une instance de la classe à partir d’une table de hachage, en passant chaque valeur de propriété et en passant le nom du livre et de l’auteur. La classe ne définit pas le constructeur par défaut.

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

L’appel du constructeur par défaut retourne une exception de méthode. Le constructeur automatique par défaut est défini uniquement pour une classe lorsque la classe ne définit aucun constructeur. Étant donné que ExampleBook3 définit plusieurs surcharges, le constructeur par défaut n’est pas automatiquement ajouté à la classe.

Exemple 4 - Chaînage de constructeurs avec une méthode partagée

Cet exemple montre comment écrire du code partagé réutilisable pour les constructeurs. Les classes PowerShell ne peuvent pas utiliser le chaînage de constructeurs. Par conséquent, cet exemple de classe définit une Init() méthode à la place. La méthode a plusieurs surcharges. Les surcharges avec moins de paramètres appellent les surcharges plus explicites avec des valeurs par défaut pour les paramètres non spécifiés.

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

Exemple 5 : constructeurs de classes dérivées

Les exemples suivants utilisent des classes qui définissent les constructeurs statiques, par défaut et paramétrables pour une classe de base et une classe dérivée qui hérite de la classe de base.

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

Le bloc suivant montre la messagerie détaillée permettant d’appeler les constructeurs de classe de base. Le message du constructeur statique n’est émis que la première fois qu’une instance de la classe est créée.

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)

Le bloc suivant affiche la messagerie détaillée permettant d’appeler les constructeurs de classes dérivées dans une nouvelle session. La première fois qu’un constructeur de classe dérivée est appelé, les constructeurs statiques pour la classe de base et la classe dérivée sont appelés. Ces constructeurs ne sont pas appelés à nouveau dans la session. Les constructeurs de la classe de base s’exécutent toujours avant les constructeurs de la classe dérivée.

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)

Ordre d’exécution du constructeur

Lorsqu’une classe instancie, le code d’un ou plusieurs constructeurs s’exécute.

Pour les classes qui n’héritent pas d’une autre classe, l’ordre est :

  1. Constructeur statique pour la classe.
  2. Surcharge de constructeur applicable pour la classe.

Pour les classes dérivées qui héritent d’une autre classe, l’ordre est :

  1. Constructeur statique pour la classe de base.
  2. Constructeur statique pour la classe dérivée.
  3. Si le constructeur de classe dérivée appelle explicitement une surcharge de constructeur de base, il exécute ce constructeur pour la classe de base. S’il n’appelle pas explicitement un constructeur de base, il exécute le constructeur par défaut pour la classe de base.
  4. Surcharge de constructeur applicable pour la classe dérivée.

Dans tous les cas, les constructeurs statiques ne s’exécutent qu’une seule fois dans une session.

Pour obtenir un exemple de comportement et d’ordre du constructeur, consultez l’exemple 5.

Constructeurs masqués

Vous pouvez masquer les constructeurs d’une classe en les déclarant avec le hidden mot clé. Les constructeurs de classes masquées sont les suivants :

  • Non inclus dans la sortie par défaut de la classe.
  • Non inclus dans la liste des membres de classe retournés par l’applet de Get-Member commande. Pour afficher les propriétés masquées avec Get-Member, utilisez le paramètre Force .
  • Non affiché dans la saisie semi-automatique de tabulation ou IntelliSense, sauf si la saisie semi-automatique se produit dans la classe qui définit la propriété masquée.
  • Membres publics de la classe. Ils sont accessibles et modifiés. Masquage d’une propriété ne le rend pas privé. Elle masque uniquement la propriété comme décrit dans les points précédents.

Remarque

Lorsque vous masquez un constructeur, l’option new() est supprimée d’IntelliSense et des résultats de saisie semi-automatique.

Pour plus d’informations sur la hidden mot clé, consultez about_Hidden.

Constructeurs statiques

Vous pouvez définir un constructeur comme appartenant à la classe elle-même au lieu d’instances de la classe en déclarant le constructeur avec le static mot clé. Constructeurs de classe statique :

  • Appelez uniquement la première fois qu’une instance de la classe est créée dans la session.
  • Impossible d’avoir de paramètres.
  • Impossible d’accéder aux propriétés ou méthodes d’instance avec la $this variable.

Constructeurs pour les classes dérivées

Lorsqu’une classe hérite d’une autre classe, les constructeurs peuvent appeler un constructeur de la classe de base avec le base mot clé. Si la classe dérivée n’appelle pas explicitement un constructeur de la classe de base, elle appelle le constructeur par défaut pour la classe de base à la place.

Pour appeler un constructeur de base nondefault, ajoutez : base(<parameters>) après les paramètres du constructeur et avant le bloc de corps.

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

Lors de la définition d’un constructeur qui appelle un constructeur de classe de base, les paramètres peuvent être l’un des éléments suivants :

  • Variable de n’importe quel paramètre sur le constructeur de classe dérivé.
  • Toute valeur statique.
  • Toute expression qui prend la valeur d’une valeur du type de paramètre.

Pour obtenir un exemple de constructeur sur une classe dérivée, consultez l’exemple 5.

Constructeurs chaînants

Contrairement à C#, les constructeurs de classes PowerShell ne peuvent pas utiliser le chaînage avec la : this(<parameters>) syntaxe. Pour réduire la duplication de code, utilisez une méthode masquée Init() avec plusieurs surcharges dans le même effet. L’exemple 4 montre une classe à l’aide de ce modèle.

Ajout de propriétés et de méthodes d’instance avec Update-TypeData

Au-delà de déclarer des propriétés et des méthodes directement dans la définition de classe, vous pouvez définir des propriétés pour les instances d’une classe dans le constructeur statique à l’aide de l’applet Update-TypeData de commande.

Utilisez cet extrait de code comme point de départ pour le modèle. Remplacez le texte de l’espace réservé entre crochets angle en fonction des besoins.

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

Conseil

L’applet Add-Member de commande peut ajouter des propriétés et des méthodes à une classe dans des constructeurs non statiques, mais l’applet de commande est exécutée chaque fois que le constructeur est appelé. L’utilisation Update-TypeData dans le constructeur statique garantit que le code permettant d’ajouter les membres à la classe ne doit s’exécuter qu’une seule fois dans une session.

Ajoutez uniquement des propriétés à la classe dans des constructeurs non statiques lorsqu’elles ne peuvent pas être définies avec Update-TypeData, comme les propriétés en lecture seule.

Pour plus d’informations sur la définition des méthodes d’instance avec Update-TypeData, consultez about_Classes_Methods. Pour plus d’informations sur la définition des propriétés d’instance avec Update-TypeData, consultez about_Classes_Properties.

Limites

Les constructeurs de classes PowerShell présentent les limitations suivantes :

  • Le chaînage du constructeur n’est pas implémenté.

    Solution de contournement : définissez des méthodes masquées Init() et appelez-les à partir des constructeurs.

  • Les paramètres du constructeur ne peuvent pas utiliser d’attributs, y compris les attributs de validation.

    Solution de contournement : réaffectez les paramètres dans le corps du constructeur avec l’attribut de validation.

  • Les paramètres du constructeur ne peuvent pas définir de valeurs par défaut. Les paramètres sont toujours obligatoires.

    Solution de contournement : aucune.

  • Si une surcharge d’un constructeur est masquée, chaque surcharge du constructeur est traitée comme masquée également.

    Solution de contournement : aucune.

Voir aussi