Classes, OOP, and User-defined Types

Roger PoonBy Roger Poon

JS++ Designer and Project Lead

Up until now, we've been declaring variables, looping over data, and writing 'if' and other conditional statements. These operations comprise the "imperative programming" paradigm where we describe "how" a program operates step by step (or, more specifically, statement by statement).

Oftentimes, in real-world programming, we want to be able to describe real-world objects. For example, in an employee database, we need to be able to describe "employees" – and maybe even specific types of employees such as programmers, managers, salespeople, and so on. In a video game, we need to be able to describe the hero, the enemies, bullets, weapons, equipment, and other items. This need gave rise to the object-oriented programming (OOP) paradigm, most notably with the C++ programming language (although OOP itself predates C++) and then extending to Java, Python, C#, PHP, Objective-C, Swift, and many other modern languages.

JS++ provides access to object-oriented programming (OOP) via classes, which also create user-defined types. JS++ is an extension of the JavaScript ECMAScript 3 specification, which did not provide class support. Furthermore, JS++ classes are unique from class systems and libraries that tried to add OOP to JavaScript, a language that is "dynamically-typed" – where data types are determined at runtime (as we explored previously). Instead, JS++ classes operate naturally with many compile-time concepts where static typing and static analysis are used (where data types and errors are analyzed and checked at compile time): nominal typing, method overloading, parametric polymorphism (generic programming), compile-time overload resolution, virtual methods, and so on. In this way, object-oriented programming in JS++ is very similar to the OOP available in C++, Java, and C#. Therefore, design patterns and best practices that were developed over decades of experience in the aforementioned programming languages, from banking to rocketry, are also immediately applicable to JS++.

In this chapter, we will introduce basic OOP in JS++ by creating animal objects that we will render to a web page. We will then progressively add interactivity to these animal objects to illustrate core OOP concepts. We will also cover the four fundamentals of OOP: abstraction, encapsulation, inheritance, and polymorphism.

Classes and User-Defined Types

Classes are the basic foundation of object-oriented programming in JS++. We can declare a class using the 'class' keyword:

        class Animal
        {
        }
        

By declaring a class, you are also creating your own user-defined data type. To use a game development analogy, if you want to declare a function that operates on bullets, you don't want data representing potion objects to potentially be operated on. This goes back to the correctness guarantees that JS++ provides as we previously explored.

Since classes allow us to create our own user-defined data types, let's explore how this can be used in practice. Create a folder named 'OOP'. Inside the 'OOP' folder, create a file named error.jspp and enter the following code:

        class Animal
        {
        }
        class Chair
        {
        }

        void startWalking(Animal a) {
        }

        Animal dog = new Animal();
        Chair chair = new Chair();
        startWalking(chair); // intentional, let's see the error
        

Try compiling. You should see this compile error:

[ ERROR ] JSPPE5024: No overload for `startWalking' matching signature `startWalking(Chair)' at line 13 char 0 at error.jspp

We want our 'startWalking' function to make an object of type 'Animal' start walking. We don't want to accidentally or potentially be able to pass in an object of type 'Chair'. Change the 'startWalking' function call:

        // startWalking(chair); // intentional, let's see the error
        // to:
        startWalking(dog);
        

Although our 'startWalking' function is an empty function that doesn't do anything (e.g. make an actual 'Animal' object walk), we're able to see the basics of how user-defined types can be used in real-world code to prevent mistakes. If you compile the revised error.jspp to pass in the 'dog' object, it should successfully compile with no errors.

You can now delete error.jspp. We won't be needing it anymore. It's always good to keep your code clean and remove code that is no longer used.

Instantiation

You may have noticed that we used the 'new' keyword a couple times in our previous code:

        Animal dog = new Animal();
        Chair chair = new Chair();
        

The 'new' keyword is used for a process called "instantiation." Classes are like "blueprints" for objects. The objects are the "instances" of the class. In the two lines of code above, 'dog' is the object instance of the 'Animal' blueprint (class) and 'chair' is an instance of the 'Chair' blueprint. Since we can have multiple "instances" of the class, this enables us to create multiple dogs with different attributes, such as dogs with different names, different weights, descending from different breeds, and so on.

To recap: the 'class' keyword creates the blueprint, and the 'new' keyword creates an object/instance of that blueprint.

Setting Up Our OOP Project

We're now going to begin our OOP project. We'll create classes for different animals, render them to a web page, make them talk with speech bubbles, and more.

First, we need to download some resources. Inside the 'OOP' project folder, create four subfolders: 'build', 'libs', 'src', and 'style'.

Head over to Icofont.com to download Icofont. Icofont is an "icon font." For those of you familiar with the Windows "Wingdings" font, this is the same idea. Icon fonts give us graphics and icons – in the form of font characters – that we can use in our applications. Icon fonts have the added advantage that we can change the color of the icon simply by changing the font color. This makes icon fonts ideal for the web and user interfaces.

Download and unzip Icofont to your 'libs' subfolder. Your directory structure should now look like this:

        OOP
        |_ build
        |_ libs
             |_ Icofont
                  |_ css
                  |_ fonts
        |_ src
        |_ style
        

In the 'style' subfolder, create an empty 'style.css' file.

In your 'src' subfolder, create an empty main.jspp file. Now, again in the 'src' subfolder, create a folder named 'Animals' and put the following *empty* files inside:

  • Animal.jspp
  • Cat.jspp
  • Dog.jspp
  • Panda.jspp
  • Rhino.jspp

Finally, in our root 'OOP' project folder, create an 'index.html' file with the following code:

        <!DOCTYPE html>
        <head>
        <title>JS++ Animals OOP Project</title>
        <link rel="stylesheet" type="text/css" href="lib/icofont/css/icofont.css">
        <link rel="stylesheet" type="text/css" href="style/style.css">
        </head>
        <body>

        <div id="content"></div>

        <script src="http://code.jquery.com/jquery-1.12.4.min.js"></script>
        <script src="build/app.jspp.js"></script>
        </body>
        </html>
        

The HTML should be straightforward by now. We created a 'div' element which will be the container for the content we will dynamically generate via jQuery and JS++. The new tags are for including our CSS files used for styling. Also worth noting is the 'script' tag pointing to "build/app.jspp.js" which will contain our generated JS++ application. (When JS++ compiles multiple input source files, the default output name is usually 'app.jspp.js'.)

Your final directory structure should look something like this:

        OOP
        |_ build
        |_ libs
             |_ Icofont
                  |_ css
                       |_ icofont.css
                  |_ fonts
                       |_ icofont.eot
                       |_ icofont.svg
                       |_ icofont.ttf
                       |_ icofont.woff
        |_ src
             |_ Animals
                  |_ Animal.jspp
                  |_ Cat.jspp
                  |_ Dog.jspp
                  |_ Panda.jspp
                  |_ Rhino.jspp
             |_ main.jspp
        |_ style
             |_ style.css
        index.html