{"id":10055,"date":"2015-10-21T06:00:00","date_gmt":"2015-10-21T13:00:00","guid":{"rendered":"https:\/\/www.sapien.com\/blog\/?p=10055"},"modified":"2015-10-21T17:24:13","modified_gmt":"2015-10-22T00:24:13","slug":"why-do-we-need-constructors","status":"publish","type":"post","link":"https:\/\/dev.sapien.com\/blog\/2015\/10\/21\/why-do-we-need-constructors\/","title":{"rendered":"Why Do We Need Constructors?"},"content":{"rendered":"<p>While traveling after PowerShell Summit Europe in Stockholm, I was honored to be the guest of the Microsoft Technical User Group in Oslo, Norway (<a href=\"https:\/\/twitter.com\/mtug_norge\">@MTUG_Norge<\/a>). This well-established user group meets on the beautiful campus of the University of Oslo, a short light-rail ride from downtown Oslo.<\/p>\n<p>We got together for a hands-on lab on classes in PowerShell 5.0. It was an experienced group &#8212; mainly IT operations folks &#8212; who are well-versed in PowerShell. The concepts are all new, but the group of 35-40 people were quick to understand them.<\/p>\n<p>One thoughtful guy asked a particularly good question: Why do we need constructors? As PowerShell scripters, we&#8217;re used to the <a href=\"http:\/\/go.microsoft.com\/fwlink\/p\/?linkid=293993\">New-Object<\/a> cmdlet and <a href=\"http:\/\/technet.microsoft.com\/en-us\/library\/jj159398(v=wps.640).aspx\">creating objects<\/a> with PSCustomObject, PSObject, and hash tables. Why do we need yet another concept in object creation?<\/p>\n<h1>Why Constructors?<\/h1>\n<p>The short answer is that, unbeknownst to us, we&#8217;ve been using constructors all along. But, in its quest to make us successful, PowerShell has (mostly) hidden the concept from us.<\/p>\n<p>A <b><i>constructor<\/i><\/b> is a special method of a class that initializes new objects or <i>instances<\/i> of the class. Without a constructor, you can&#8217;t create instances of the class. Imagine that you could create a class that represents files, but without constructors, you couldn&#8217;t create any files based on the class.<\/p>\n<p>Some types of classes, including <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/k535acbf(v=vs.71).aspx\">abstract classes<\/a> and <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/dyc5b94e(v=vs.71).aspx\">interfaces<\/a>, don&#8217;t need constructors, because you don&#8217;t create instances of them. Instead, you use them as base classes and derive subclasses from them.<\/p>\n<p>(Cool digression: Abstract classes aren&#8217;t required to have constructors, but they can have them. You can call the constructor of an abstract class to create a new instance of a <b><i>subclass<\/i><\/b> that&#8217;s based on (&#8220;derived from&#8221;) the abstract class. Thanks to <a href=\"https:\/\/twitter.com\/dfinke\">Doug Finke<\/a> for his excellent tutelage.)<\/p>\n<p>(Fun fact: You can implement multiple interfaces, but you can derive a class from only one base class.)<\/p>\n<h1>How do you use a constructor?<\/h1>\n<p>Even though constructors are methods, you don&#8217;t call them directly.<\/p>\n<p>Instead, <b><i>constructors determine the parameter values or &#8220;arguments&#8221;<\/i><\/b> that you are required to provide to the <b>New-Object<\/b> cmdlet or the <b>New<\/b> static method.<\/p>\n<p>For example, let&#8217;s create a Tree class that has two properties, Species (a string) and Height (an integer).<\/p>\n<pre lang=\"PowerShell\">class Tree {\r\n    [String]$Species\r\n    [int32]$Height\r\n    \u2026\r\n}<\/pre>\n<p>The Tree class also has one constructor that takes one string value (for the species) and one integer value (for the height).<\/p>\n<p># In Help: Constructor1: [String]$Species, [Int32]$Height<\/p>\n<p>When you create a tree, you must provide precisely one string and one integer in the specified order. (The order matters because you don&#8217;t type parameter names.)<\/p>\n<pre lang=\"PowerShell\">New-Object -TypeName Tree -ArgumentList 'Mimosa', 10<\/pre>\n<p>-or-<\/p>\n<pre lang=\"PowerShell\">[Tree]::New('Mimosa', 10)<\/pre>\n<p>This works:<\/p>\n<pre class=\"output\">Species Height\r\n------- ------\r\nMimosa 10<\/pre>\n<p>If you try to create a Tree with missing, extra, or different objects, the command fails.<\/p>\n<pre class=\"output\">PS C:\\&gt; New-Object -TypeName Tree -ArgumentList 10\r\n\r\nNew-Object : Cannot find an overload for \"Tree\" and the argument count: \"1\".\r\nAt line:1 char:1\r\n+ New-Object -TypeName Tree -ArgumentList 10\r\n+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodException\r\n+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand<\/pre>\n<h1>How do I write a constructor?<\/h1>\n<p>Constructors <i>initialize<\/i> the new object, that is, they set the startup property values for the object. They might also do other things necessary to make the object usable.<\/p>\n<p>You can distinguish constructors from other methods of a class because <b>constructors always have the same name as the class<\/b>. If the class is Tree, it&#8217;s constructors are all named Tree, too.<\/p>\n<p>A <i>constructor<\/i> is a method, so it has a script block and (optional) parameters.<\/p>\n<p>Syntax:<\/p>\n<pre lang=\"powershell\" escaped=\"true\">&lt;ClassName&gt; ( [&lt;optional_parameters&gt;] ) {\r\n    &lt;statements and commands\u2026&gt;\r\n}<\/pre>\n<p>For example, the Tree class has a constructor that takes a Species string. Like the class, the constructor is named Tree.<\/p>\n<pre lang=\"PowerShell\">Tree ( [string]$Species ) {\r\n    $this.Species = $Species\r\n}<\/pre>\n<p>You can have multiple constructors. But, because the parser looks only at parameter types, not names, the constructors must take different types.<\/p>\n<p>This constructor in the Tree class takes a string and an integer. It assigns the string to the Species property and the integer to the Height property.<\/p>\n<pre lang=\"PowerShell\">Tree ( [string]$Species, [int32]$Height ) {\r\n\r\n    $this.Species = $Species\r\n    $this.Height = $Height\r\n}<\/pre>\n<p>Here is the tree class with its Tree constructors.<\/p>\n<pre lang=\"PowerShell\">class Tree ()\r\n{\r\n\r\n    [String]$Species\r\n    [int32]$Height\r\n\r\n    # Here is a constructor. Notice the name.\r\n    Tree ( [string]$Species ) {\r\n        $this.Species = $Species\r\n    }\r\n\r\n    # Here is another constructor. It's also named Tree, but it takes different parameter types.\r\n    Tree ( [string]$Species, [int32]$Height ) {\r\n        $this.Species = $Species\r\n        $this.Height = $Height\r\n    } \r\n\r\n    # Here is a different method with a different name.\r\n    [int32] Grow ( [uint32]$Amount) )\r\n    {\r\n        $this.Height += $Amount\r\n        return $this.Height\r\n    }\r\n}<\/pre>\n<p>Constructors don&#8217;t return anything. A\u00a0return type is not permitted.<\/p>\n<p>To use the first constructor, I need to submit a string, such as &#8216;Mimosa&#8217;.<\/p>\n<pre lang=\"PowerShell\">New-Object -Typename Tree -ArgumentList 'Mimosa'<\/pre>\n<p>-or-<\/p>\n<pre lang=\"PowerShell\">[Tree]::New('Mimosa')<\/pre>\n<p>To use the second constructor, I submit a string and an integer, in that order.<\/p>\n<pre lang=\"PowerShell\">New-Object -Typename Tree -ArgumentList 'Mimosa, 10'<\/pre>\n<p>-or-<\/p>\n<pre lang=\"PowerShell\">[Tree]::New('Mimosa', 10)<\/pre>\n<h1>How do I find the constructors of a class?<\/h1>\n<p>The simplest way to get the constructors in a class is to use the <b>New<\/b> static property of all classes.<\/p>\n<p>The syntax is:<\/p>\n<pre lang=\"powershell\" escaped=\"true\">[&lt;ClassName&gt;]::New<\/pre>\n<p>For example, to get the constructors in the Tree class:<\/p>\n<pre class=\"output\">PS C:\\&gt; [Tree]::New\r\n\r\nOverloadDefinitions\r\n-------------------\r\nTree new(string Species)\r\nTree new(string Species, int Height)<\/pre>\n<h3>Must I write a constructor?<\/h3>\n<p>Surprisingly, the answer is no.<\/p>\n<p>When you create a class, Windows PowerShell creates a default constructor for you.\u00a0A <em>default constructor<\/em>\u00a0has no parameters and takes no arguments or values.\u00a0You might\u00a0hear it\u00a0called a <em>null constructor <\/em>or\u00a0<em>parameter-less constructor<\/em>.<\/p>\n<p>For example, if I create a Tree class with nothing in it, I can create a Tree object.<\/p>\n<pre class=\"output\">PS C:\\&gt; class Tree {}\r\nPS C:\\&gt; $myTree = New-Object -TypeName Tree\r\nPS C:\\&gt; $myTree | Get-Member\r\n\r\n   TypeName: Tree\r\n\r\nName        MemberType Definition\r\n----        ---------- ----------\r\nEquals      Method     bool Equals(System.Object obj)\r\nGetHashCode Method     int GetHashCode()\r\nGetType     Method     type GetType()\r\nToString    Method     string ToString()<\/pre>\n<p>If you use the New static property of the Tree class, you can see the default constructor that Windows PowerShell created for you.<\/p>\n<pre class=\"output\">PS C:\\&gt; [Tree]::New\r\n\r\nOverloadDefinitions\r\n-------------------\r\nTree new()<\/pre>\n<p>However, if you add a constructor to the Tree class, the &#8220;free&#8221; default constructor disappears.<\/p>\n<pre class=\"output\">PS C:&gt; class Tree {\r\n&gt;&gt; Tree ([String]$Species) {}\r\n&gt;&gt; }\r\n&gt;&gt;\r\nPS C:\\&gt; [Tree]::New\r\n\r\nOverloadDefinitions\r\n-------------------\r\nTree new(string Species)<\/pre>\n<p>If you want a default constructor in your class, you need to add it explicitly. (And, you should, because it allows people to use hash tables to create objects. I&#8217;ll explain in detail in a later blog post.)<\/p>\n<pre class=\"output\">PS C:\\&gt; class Tree {\r\n&gt;&gt;\r\n&gt;&gt; Tree () {}\r\n&gt;&gt; Tree ([String]$Species) {}\r\n&gt;&gt; }\r\n&gt;&gt;\r\nPS C:\\&gt; [Tree]::New\r\n\r\nOverloadDefinitions\r\n-------------------\r\nTree new()\r\nTree new(string Species)<\/pre>\n<p>&nbsp;<\/p>\n<p>Constructors are very new to Windows PowerShell users, but we&#8217;ve been using them whenever we use the New-Object cmdlet, and Windows PowerShell has been using them to create objects whenever we use a Get cmdlet. Now, in Windows PowerShell 5.0, we can create them, as well as use them.<\/p>\n<p>Thanks again to MTUG_Norge and its members for having me. I really enjoyed it.<\/p>\n<p><i>June Blender is a technology evangelist at SAPIEN Technologies, Inc and a Windows PowerShell MVP. You can reach her at <\/i><a href=\"mailto:juneb@sapien.com\"><i>juneb@sapien.com<\/i><\/a><i>\u00a0and follow her on Twitter at <\/i><a href=\"https:\/\/twitter.com\/juneb_get_help\"><i>@juneb_get_help<\/i><\/a><i>.<\/i><\/p>\n","protected":false},"excerpt":{"rendered":"<p>While traveling after PowerShell Summit Europe in Stockholm, I was honored to be the guest of the Microsoft Technical User Group in Oslo, Norway (@MTUG_Norge). This well-established user group meets on the beautiful campus of the University of Oslo, a short light-rail ride from downtown Oslo. We got together for a hands-on lab on classes [&hellip;]<\/p>\n","protected":false},"author":31,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[1033,941,25],"tags":[612,934,961,524,997],"class_list":["post-10055","post","type-post","status-publish","format-standard","hentry","category-classes-in-powershell-5-0","category-powershell-5-0","category-windows-powershell","tag-classes","tag-juneb","tag-powershell-5-0","tag-user-groups","tag-windows-powershell"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/10055","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/users\/31"}],"replies":[{"embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/comments?post=10055"}],"version-history":[{"count":24,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/10055\/revisions"}],"predecessor-version":[{"id":10147,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/10055\/revisions\/10147"}],"wp:attachment":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/media?parent=10055"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/categories?post=10055"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/tags?post=10055"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}