Classes - variables with complex properties

Apr 27, 2021

Controlling variable values and properties

About Classes

This is the second of three posts in a mini-series. Part one was published last week and the final part will be out next week. Part one covered enums in some detail and the examples here follow on from there. It might be worth a quick read before you try the sample code here.

So what’s a class?

We can consider a PowerShell class to be a blueprint of an object that defines what type of thing it is and how it will behave. For this functionality you will need to be working on PowerShell version 5. We can define our class with syntax layout that is quite similar to the way a function is declared. We are going to work with a class that describes a fictional series of televisions.

PS> Class Television {
    [string]$Manufacturer
    [string]$Model
    [int]$Screensize_CM
    [int]$Channel
}

With that done, when we are ready in our code we can then declare a variable to have a datatype of our class rather than one of the more common datatypes such as INT or STRING etc and when we inspect that variable we can see the properties that we wanted for our object

PS> $TV = [Television]::new()

$TV

image

Setting values for these properties is very simple, we ‘dot reference’ the property of our variables and assign the value we need

PS> $TV.Manufacturer = 'Sony'
$tv.Model = "TV123"

image

With this example Television class some properties are static, the size and manufacturer are not going to change over time but to make things a bit more realistic it would be good if properties like the Channel value can be set and changed at will. If we want to represent this real world functionality in our code then we can declare a method to do what we need. Within our class defintion we can provide logic for setting the channel property and also to instruct the object to increment or decrement the channel property as if we were pressing the channel up / down button on the remote control. In terms of retrieving property values we can also add a method that will give a string output which describe the object at that point in time - the ToString method that we see on other objects. Let’s do this with a new class - Television2.

PS> Class Television2 {
    [string]$Manufacturer
    [string]$Model
    [int]$Screensize_CM
    [int]$Channel

    [void]SetChannel([int]$chan) {
        $this.Channel = $chan
    }

    [int]ChannelUp() {
        $this.Channel ++
        return ($this.Channel)
    }
    
    [int]ChannelDown() {
        $this.Channel --
        return ($this.Channel)
    }

    [string]ToString() {
        return ("The {0} {1} has a screen size of {2}cm" -f $this.Manufacturer, $this.Model, $this.Screensize_CM)
    }
}

# define a new object of this new type of TV
$TV = [television2]::new()

# set some basic property values
$TV.Manufacturer = 'Samsung'
$tv.Model = "s46"
$tv.Screensize_CM = 120

# set the new Channel property.
# we dont get any response from this method as we set it to [void]
$tv.SetChannel(4)

# check out the object
$tv

image

So we can see that our object has the values set by direct assignment (eg $TV.Manufacturer = 'Samsung') but also using the object method SetChannel that we created with the line $tv.SetChannel(4).

Now we will test the ChannelUp and ChannelDown methods.

# test out the new methods
$tv.ChannelUp()
$tv.ChannelDown()
# because both methods return an INT we see the new Channel setting

# calling the ToString method gets all of the object properties in the string format that we specified
$tv.ToString()

The ChannelUp and ChannelDown methods were written to do two things - the first ($this.Channel ++) is to change the channel up or down by one and then the second (return ($this.Channel)) is to return the new channel value. image

# something for the reader to do: add a Volume property and methods to control the TV volume selection

Classes can have properties that are themselves classes, or Enums

If we create an enum called TVChannel that represents some of the TV channels here in the UK, we can then use that in a class definition as the data type for the TVChannel property of our planned objects.

enum TVChannel{
    BBC1 = 1
    BBC2 = 2
    ITV = 3
    Channel4 = 4
    Channel5 = 5
}

Class Television3 {
    [string]$Manufacturer
    [string]$Model
    [int]$Screensize_CM
    [TVChannel]$Channel

    [void]SetChannel([int]$chan) {
        $this.Channel = $chan
    }
    [int]ChannelUp() {
        $this.Channel ++
        return ($this.Channel)    
    }
    [int]ChannelDown() {
        $this.Channel --
        return ($this.Channel)
    }

    [string]ToString() {
        return ("The {0} {1} has a screen size of {2}cm. It's currently set to show channel {3}" -f $this.Manufacturer, $this.Model, $this.Screensize_CM, $this.Channel)
    }
}

Great but what advantage does this give us?

If we do this then the way that our script objects act changes subtely. Using the enum and class defined above, let’s create a new TV object and check out the object and it’s .ToString() output.

# define a new object of our largest type of TV
$TV = [television3]::new()
# set some basic property values
$TV.Manufacturer = 'Toshiba'
$tv.Model = "t200"
$tv.Screensize_CM = 200

# set the new Channel property - note we dont get any response from this method as we set it to [void]
$tv.SetChannel(4)

# check out the object
$tv

image

Instead of seeing the channel number as before, using the enum for the TVChannel gives us the channel name in output.

I hope you found this useful and that you’ll come back next week for part three of this mini-series.

Further reading