Class-First Coding
© 24 Oct 2013 Luther Tychonievich
Licensed under Creative Commons: CC BY-NC-ND 3.0
other posts

Learning to Program

Lesson 4: new and Constructors

 

Conceptual Overview

In the last lesson we discussed the stack (a worker’s memory of what it is doing) and the heap (the place where all objects reside). This lesson discusses how new objects come into existence.

Recall that a class is a description of a kind of object. You might think of “‍number‍” as a class and “‍3‍” or “‍87‍” as objects, instances of the “‍number‍” class. You can’t do much with a class: you need an actual object for the methods to act on.

This distinction can get a bit confusing sometimes. Partly this is because there are many levels of things describing other things. For example, class Car is a description of the state and behavior of car objects, but car objects themselves are descriptions of real-world cars. All of the words we usually use to distinguish between real and conceptual things get changed in programming to be directions instead of designations. “‍Abstract‍”, “‍concrete‍”, “‍physical‍”, “‍description‍”, etc.: any one of them could be used to describe anything depending on what that thing is being compared to.

This is part of the reason that in programming we make crisp definitions for One difference between computing and many other fields is that computing disciplines re-define existing words instead of introducing new ones based on Latin or people’s names. I got back and forth on if I think this is good or bad decision. “‍class‍”, “‍object‍”, “‍value‍”, “‍instance‍”, and “‍type‍”. A class defines the states and behaviors of objects. Objects are regions of memory that contain values for all of the states defined by a class. A value is either a primitive value, such as 3 or true, or it is a description of where another object is located in memory. If class C describes object o then o is an instance of C and C is the type of o.

To make an object, then, requires three steps. We need to

  1. get a chunk of memory in which to store the object’s state;
  2. know what type of object that memory represents; and
  3. assign a value to each field in the object’s state.

The result of these three steps, which are usually handled together, is a value: a description of where the new object is located in memory.

Aside: who stores the type?

There is ongoing research and heated debate among computing researchers about the simple question “‍how do we track what type each object has?‍” Glossing over myriad details, there are three options. First, we might make the type of an object be part of its state. Second, we might ensure that each variable only refers to one type, ever, so that we never need to ask an object what type it is and thus it need not know. Third, we might do both. Doing both might seem like a waste, replicating information unnecessarily, but it is what all of the languages I’ve used in this lesson series (C++, Java, C#, and D) actually do. A few older languages, such as C and Fortran, only track type by variables; many that are targeting shorter programs, such as Javascript, Python, PHP, Ruby, and most mathematical languages, only track type inside the state of an object.

Coding object creation

In the languages which I am discussing herein, a new object is usually created as follows: TheType newName = new TheType(value, value, ...); This single line of code has a lot of things going on, many of which we have discussed in previous lessons.

TheType newName is how we define a variable. Technically we don’t need to do this, but without a variable we won’t have a way of talking about the newly created object.

newName = ... is how we assign a value to a variable. Again, technically we don’t need to do this, but if we don’t assign it then we won’t have a way of talking about the newly created object.

new TheType is new to this lesson. It does steps 1 and 2: getting a chunk of memory and deciding what type is stored there.

TheType(value, value, ...) looks a lot like a method invocation. It is actually invoking a special kind of method called a “‍constructor‍”, the job of which is to do step 3: assigning a value to each field that makes up the new object’s state.

Coding constructors

The exact syntax for coding a constructor varies from language to language. One thing they have in common: constructors don’t have a return type (not void, not anything else). A constructor can’t be invoked the way other methods can so the idea of a return type is not meaningful for them.

In C++, Java, and C# constructors have the same name as the class so we would write class Fraction {
int numerator;
int denominator;
Fraction(int n, int d) {
this.numerator = n;
this.denominator = d;
}
}

In D constructors are named “‍this‍” (the same as the special “‍the object‍” variable) so we would write class Fraction {
int numerator;
int denominator;
this(int n, int d) {
this.numerator = n;
this.denominator = d;
}
}

In both cases, we could make an object representing
2
3
using the above constructor by writing Fraction f = new Fraction(2, 3); Once we have this fraction we can use it to invoke other fraction methods or as an argument in other method invocations.


The following D code snippets use some ideas we have not yet discussed, such as the * and > operators and the order in which things happen within a method body; but they also illustrate new, constructors, and using objects.

class Fraction { int numerator; int denominator; this(int n, int d) { this.numerator = n; this.denominator = d; } bool isBiggerThan(Fraction other) { int a = this.numerator * other.denominator; int b = other.numerator * this.denominator; return a > b; } }
Fraction x = new Fraction(2, 3); Fraction y = new Fraction(11, 14); bool xSmaller = y.isBiggerThan(x);



Looking for comments…



Loading user comment form…