Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constructor chaining in PowerShell - call other constructors in the same class

I was doing some testing and stumbled upon the following:

You can overload methods in PoShv5 as you wish. If you call the method without parameters, it can internally call the method with parameters, to keep your code non-redundant. I expected this to be also true for constructors.

In this example, the last constructor is working as expected. The other constructors only return objects without set values.

Class car {
    [string]$make
    [string]$model
    [int]$Speed
    [int]$Year

    speedUp (){
        $this.speedUp(5)
    }
    speedUp ([int]$velocity){
        $this.speed += $velocity
    }

    # Constructor
    car () {
        [car]::new('mall', $Null, $null)
    }

    car ([string]$make, [string]$model) {
        [car]::new($make, $model, 2017)
    }

    car ([string]$make, [string]$model, [int]$Year) { 
        $this.make = $make
        $this.model = $model
        $this.Year = $year
    }
}

[car]::new() # returns "empty" car
[car]::new('Make', 'Nice model') # returns also an "empty" one
[car]::new( 'make', 'nice model', 2017) # returns a "filled" instance

Is there a way to fix this? Did I miss something?

like image 801
restless1987 Avatar asked Jun 07 '17 12:06

restless1987


People also ask

Can a constructor call another constructor of the same class?

The invocation of one constructor from another constructor within the same class or different class is known as constructor chaining in Java. If we have to call a constructor within the same class, we use 'this' keyword and if we want to call it from another class we use the 'super' keyword.

Can this keyword call another constructor in constructor chaining?

Constructor chaining refers to the ability to call a constructor inside another constructor. You can use a constructor chain either within the same class or even with another one. For the latter, the constructor should be through inheritance from the super class.

How do you call a parameterized constructor from another constructor in the same class?

Constructor chaining can be done in two ways: Within same class: It can be done using this() keyword for constructors in the same class. From base class: by using super() keyword to call the constructor from the base class.

Can a constructor call another?

Constructor Calling form another Constructor The calling of the constructor can be done in two ways: By using this() keyword: It is used when we want to call the current class constructor within the same class. By using super() keyword: It is used when we want to call the superclass constructor from the base class.


1 Answers

To complement Mathias R. Jessen's helpful answer:

The recommended approach is to use hidden helper methods to compensate for the lack of constructor chaining:

Class car {

    [string]$Make
    [string]$Model
    [int]$Year

    speedUp (){
        $this.speedUp(5)
    }
    speedUp ([int]$velocity){
        $this.speed += $velocity
    }

    # Hidden, chained helper methods that the constructors must call.
    hidden Init([string]$make)                 { $this.Init($make, $null) }
    hidden Init([string]$make, [string]$model) { $this.Init($make, $model, 2017) }
    hidden Init([string]$make, [string]$model, [int] $year) {
        $this.make = $make
        $this.model = $model
        $this.Year = $year
    }

    # Constructors
    car () {
        $this.Init('Generic')
    }

    car ([string]$make) {
        $this.Init($make)
    }

    car ([string]$make, [string]$model) {
        $this.Init($make, $model)
    }

    car ([string]$make, [string]$model, [int]$year) { 
        $this.Init($make, $model, $year)
    }
}

[car]::new()                          # use defaults for all fields
[car]::new('Fiat')                    # use defaults for model and year
[car]::new( 'Nissan', 'Altima', 2015) # specify values for all fields

This yields:

Make    Model  Year
----    -----  ----
Generic        2017
Fiat           2017
Nissan  Altima 2015

Note:

  • The hidden keyword is more of a convention that PowerShell itself observes (such as omitting such members when outputting); members tagged this way are technically still accessible, however.

  • While you can't call a constructor of the same class directly, it is possible to do so with a base-class constructor, using C#-like syntax.

like image 111
mklement0 Avatar answered Sep 22 '22 18:09

mklement0