Instantiation

Dear Computer

Chapter 5: Objects

Instantiation

A screenwriter may introduce only so many characters before the audience gets overwhelmed. Maybe four? Eight is pushing it. An object-oriented programmer, on the other hand, brings hordes of objects onto the stage in the blink of an eye. Whereas the characters in a play must be distinct from one another, objects tend to be mass-produced. They are manufactured at scale by treating a class as a blueprint.

New Semantics

To produce an object, which is an instance of a class, we must instantiate it. In many languages, the new operator followed by a call to a constructor produces an instance, as in this C++ code:

C++
Image *image = new Image(480, 320, Image::GRAYSCALE);
Image *image = new Image(480, 320, Image::GRAYSCALE);

In Ruby, new is a static method:

Ruby
image = Image.new(480, 320, Image::GRAYSCALE)
image = Image.new(480, 320, Image::GRAYSCALE)

The new operator or method has two-fold semantics:

C++, Java, Ruby, and JavaScript all require an explicit new. Languages that prioritize brevity of expression, including Python and Kotlin, omit new from instantiations but still have its semantics. There's no new in this Kotlin instantiation:

Kotlin
val image = Image(480, 320, Image.GRAYSCALE)
val image = Image(480, 320, Image.GRAYSCALE)

C has no objects and therefore no new operator. But it does have structs, and we can write a function that initializes a struct as a constructor would. The work of new is emulated with two separate statements in this C program:

C
struct image_t *image = (struct image_t *) malloc(sizeof(image_t));
initialize_image(image, 480, 320, GRAYSCALE);
struct image_t *image = (struct image_t *) malloc(sizeof(image_t));
initialize_image(image, 480, 320, GRAYSCALE);

The first statement allocates memory, and the second initializes that memory. In a language with the two-fold semantics of new, there's no danger of forgetting one of these steps like there is in C.

Memory

Recall that the stack is where a function's local variables and parameters are stored, and the heap is where data that must live beyond a function's lifetime is stored. The new operation places objects on the heap. That seems unnecessarily strict. Why can't objects be placed on the stack? In some languages they can, but others restrict objects to the heap to improve performance. When a function finishes executing, its memory is wiped. If a function returns an object stored on the stack, then the object must be copied into the caller's memory. Objects are potentially much larger than primitives, so copying them has a higher cost. Languages like Java eliminate this cost of copying by forcing all objects to live on the heap. Returning a heap object is cheap because only a pointer is copied.

C++ does allow objects to be allocated on the stack. A new stack object is declared and initialized with simpler syntax than a typical = assignment:

C++
Image image(480, 320, Image::GRAYSCALE);
Image image(480, 320, Image::GRAYSCALE);

Even though this object is on the stack, it can be passed cheaply to called functions as a reference or a pointer. If passed as a value, the copy may be expensive.

← Object SyntaxSpecialized Classes →