ScubaManDan
ScubaManDan

Reputation: 839

Set a property for a PowerShell class on Instantiation

Is it possible to have the value of a property of a PowerShell class defined on instantiation without using a constructor?

Let's say there's a cmdlet that will return Jon Snow's current status (alive or dead). I want that cmdlet to assign that status to a property in my class.

I can do this using a constructor, but I'd like this to happen regardless of which constructor is used, or even indeed if one is used at all.

function Get-JonsCurrentStatus {
    return "Alive"
}

Class JonSnow {

    [string]
    $Knowledge

    [string]
    $Status

    #Constructor 1
    JonSnow()
    {
        $this.Knowledge = "Nothing"
        $this.Status = Get-JonsCurrentStatus
    }

    #Constructor 2
    JonSnow([int]$Season)
    {
        if ($Season -ge 6) 
        {
            $this.Knowledge = "Still nothing"
            $this.Status = Get-JonsCurrentStatus #I don't want to have to put this in every constructor
        }
    }

}

$js = [JonSnow]::new()
$js

Upvotes: 3

Views: 3203

Answers (2)

Avner
Avner

Reputation: 4556

You can initialise class properties on instantiation this way:

$jon = new-object JonSnow -Property @{"Status" = Get-JonsCurrentStatus; "Knowledge" = "Nothing"}

Upvotes: 4

mklement0
mklement0

Reputation: 437042

Unfortunately, you cannot call other constructors in the same class with : this() (though you can call a base class constructor with : base())[1]

Your best bet is a workaround with a (hidden) helper method:

function Get-JonsCurrentStatus {
    return "Alive"
}

Class JonSnow {

    [string]
    $Knowledge

    [string]
    $Status

    # Hidden method that each constructor must call
    # for initialization.
    hidden Init() {
      $this.Status = Get-JonsCurrentStatus
    }

    #Constructor 1
    JonSnow()
    {
        # Call shared initialization method.
        $this.Init()
        $this.Knowledge = "Nothing"
    }

    #Constructor 2
    JonSnow([int]$Season)
    {
        # Call shared initialization method.
        $this.Init()
        if ($Season -ge 6) 
        {
            $this.Knowledge = "Still nothing"
        }
    }

}

$js = [JonSnow]::new()
$js

[1] The reason for this by-design limitation, as provided by a member of the PowerShell team is:

We did not add : this() syntax because there is a reasonable alternative that is also somewhat more intuitive syntax wise

The linked comment then recommends the approach used in this answer.

Upvotes: 4

Related Questions