Hour 13: Classes

This lesson is to introduce organizing your apps with classes.

Overview

Libraries such as the Math library, the DataFrame library, and the Form library allow you to create different types of projects. There are many more. These libraries all use a particular mechanism to organize themselves: classes. If actions are a verb, then classes would be a noun. They are, in a sense, things that the computer can create and destroy. In this lesson, your goal is to learn how to control these funky nouns, including giving them variables and actions of their own.

Goals

You have the following goals for this lesson:

  • Learn how to write classes
  • Learn about the differences between classes and objects
  • Create variables and actions within your class

Warm up

A common metaphor in computer science is to think of actions as verbs and classes as nouns. What do you think this metaphor might mean or imply?

Vocabulary

You will be learning about the following vocabulary words:

Vocabulary
TermDefinition
ClassAn organizing structure that can contain variables and actions that acts as a blueprint for custom data types to use in a program.
ObjectAn instance of a class.
Object-oriented programmingAn approach to programming a computer related to breaking down a larger problem into classes and objects that manage the functionality of an app.
Member VariablesVariables contained within a class and outside of an action within that class.

Code

You will be using the following new pieces of code:

New Code to Learn
Quorum CodeCodeExplanation
class MyClass endclass RoboDuck endDefines a particular class for use in your program.
meme:valueThe me keyword allows you to access a member variable within an action if there is a name clash.

CSTA Standards

This lesson covers the following standards:

  • 3A-DA-10: Evaluate the tradeoffs in how data elements are organized and where data is stored.
  • 3A-AP-17: Decompose problems into smaller components through systematic analysis, using constructs such as procedures, modules, and/or objects.
  • 3A-AP-18: Create artifacts by using procedures within a program, combinations of data and procedures, or independent but interrelated programs.

Explore

Just like an informational book might have a table of contents, computer code has its own approach to organization. This becomes important not just as programs increase in size, but really in how you might think about the code. For example, your code might have pages, forms, calculations, graphics, or many other things. For students especially, who may not have invented their own app before, it can be hard to know where to start. The critical missing piece not yet discussed in these lessons is classes. Classes are an important part of what is often called object-oriented programming.

Object-Oriented Programming

Classes are sort of like a blueprint in construction or architecture. They explain to the computer, and also to the human, how a particular section of the computer's memory should be organized. A class might have data it needs to store and common actions it needs to take. Just like in architecture though, a blueprint for a house is not a house. In computer science, a class does not exist in the computer's memory. You need to instance, or create, a copy of one before you can use it. This instance is called an object.

The basic idea is that you can make a specification, then use it as many times as you want. Consider a few examples. Perhaps you are making a computer game. The game, obviously, is about robotic ducks. The ducks are dangerous, you need many of them to cause havoc for the player, and each needs to have a different, and increasingly adorable, outfit as the game progresses. You might create classes for the ducks, the clothing, or other things.

One important consideration about objects is that each copy takes up memory in the computer. The exact amount is a bit tricky to calculate and outside of scope, but an easy way to think about it is the bigger the specification, especially the number of variables stored, the more memory it takes up. Most of the time, you as the programmer do not have to worry about this. If you have 10 or 1,000 robotic ducks, you are usually fine. If you have 100 billion ducks, however, your program could run out of memory. That is a lot of ducks.

As starting point, consider the following definition for your robotic duck as a class:

class RoboDuck
    integer quackCount = 0
    action Quack
        quackCount = quackCount + 1
        say "QUACK #" + quackCount
    end
end

While the previous code is identical to the same in blocks and vice versa, in this particular case it is instructive to visually consider the blocks in this case. Notably, notice that some text is inside of the class and similarly some code is inside of the action. Visually, this appears similar in blocks as so:

This is a screen capture of code as blocks. The code is:

class RoboDuck
    integer quackCount = 0
    action Quack
        quackCount = quackCount + 1
        say "QUACK #" + quackCount
    end
end

Breaking this down, notice that the RoboDuck class has inside of it an integer with a quackCount. Importantly, this variable is not inside an action. It is inside of the class. This makes it so all actions have access to the variable. In a sense, the variable is in scope of every action. This is sometimes called a member variable or a field. Both terms mean the same thing.

If you observe color, individual lines of code show up as blue blocks. Actions show up in green, and classes show up as purple. In screen reading devices, custom auditory cues are provided that indicate the scoping depth in similar ways.

Suppose you want to use your ducks. The example below shows how you can make one. This looks similar to other objects you have created before, but this time there is no use statement because you wrote it yourself using the technique above. Suppose your program was as follows:

RoboDuck freddyDuck
RoboDuck sammyDuck
freddyDuck:Quack()
freddyDuck:Quack()
sammyDuck:Quack()

In this program, two RoboDuck objects are made, and stored in the variables freddyDuck and sammyDuck. When this program is run, it says the following:

QUACK #1
QUACK #2
QUACK #1

In regard to memory, the amount used here is so small that it is not even worth thinking about. It is only in extreme cases where the memory effects start to matter. Further, while this example defines only one variable and one action, classes can have nearly as many actions and variables as you wish. If you want to provide extra variables to describe duck outfits, locations, or life goals, you can. If you want to write extra helper actions to define what the duck can do, you can do that too. Perhaps your roboduck should be able to move, appear on screen, have accessibility information, or swim in a vault of cash. The point is that the class contains any information relevant to a specific instance of a duck and can be told to take actions.

Ignoring ducks, classes do not have much code you have to write, but they are critically important for organization. Think about it. If you need to write some math around your app, make a class. If you need to control a particular page, or some behavior, make another. In fact, everything inside of a standard library, in many programming languages, is nothing more than a class that someone wrote.

Consider a real example of a class in the standard library, the Form class itself. An abridged version is shown here:

class Form is Game, FormPrimitiveContainer
    HashTable pages
    Page currentPage = undefined
    Page mainPage = undefined
    constant text DEFAULT_PAGE_NAME = "Main"
    InterfaceOptions options = undefined

Understanding all of the code here is out of scope and would be difficult, as classes in the standard library use many advanced programming features. You do not need to understand all these to use it. That said, even just by examining the variables here and guessing what they are, you might get a sense of the kinds of things a Form can do. Notably, it manages features like:

  • All of the pages that can be loaded and unloaded by the Form
  • The current and main page
  • The default name for the main page
  • Various look and feel options, like the default colors in the app
  • Whether the app is in light or dark mode

Quirky Rules about Classes

Like seemingly anything in computer science, classes do have some quirky rules. Here are a few of them:

  • All of the pages that can be loaded and unloaded by the Form
  • A file can not have more than one class. Not all programming languages have this restriction, but Quorum does
  • Use blocks must go above a class, not below or inside it. The reason is because classes need to be told what they know about
  • Actions must be inside of classes, not outside of them
  • Variables must be either inside of classes or inside of actions

Because of these restrictions, if you are using classes, you will need more than one file in your program. In Parsons problems, these will be created for you and you can fill them in. In offline editors, you manually create a file in the environment.

Managing Multiple Files Online

In both the offline and online editors for Quorum Studio, you can use multiple files. For the Parsons problems online specifically, if classes are used, multiple files will be setup automatically for you and cannot be adjusted on a webpage. To switch between files, you need special keys CTRL + [ and CTRL + ] to move between them.These files work similarly to tabs in your favorite web browser and are automatically included when you build your code.

Getting and Setting Member Variables

Classes often store information so that it can be retrieved later. The classic example of this, as shown earlier, is the member variable. While there are many ways to manipulate data in an object, one very common design pattern is to use what are called getters and setters.

The broad idea behind a getter or setter is to control access to member variables. One common example is that you might want to check it for correctness. Consider a class that only contains a positive integer, like so:

class AbsoluteValue
    integer value = 0
end

If you want another class to access the variable, you might create a getter to access the variable and a setter to change it. This way, if you need to write custom code to control access you can. Consider if you wanted to use not allow any negative number to be in the class. You might do this as so:

class AbsoluteValue
    integer value = 0

    action GetValue returns integer
        return value
    end

    action SetValue(integer value)
        if value < 0
            value = value * -1
        end
   
        me:value = value
    end
end

In this case, there are two actions in the class, GetValue, which returns the member variable, and SetValue(integer value) that changes it. One interesting note is to observe that the name of the argument in SetValue is value, which is the same name as the member variable. This is tricky.

You might be tempted to have this line of code just be value = value, but this will not work. In such a case, you would be telling the class you want it to take the value of the parameter, what is passed, and set it to itself. The standard approach is a new piece of syntax called me. By saying me with a colon at the end, then the word value, you are telling the class that you want it to access the member variable value and set that to the parameter. This allows you to then access and change the variable in a new class, like so:

AbsoluteValue pos
pos:SetValue(-5)
output pos:GetValue()

Engage

Classes are not a concept easily translated into Parsons problems. While you can certainly learn the nuts and bolts, like where to put use statements, how to control actions, and managing scope, the real challenge with them is learning when and how to use them in real projects.

What this means is that the Parsons problems in this lesson are focused on the nuts and bolts. You will practice using member variables, calling actions, and placing lines like use statements in the correct spot. That said, you may want to consider balancing out these kinds of problems with some small or mid-sized projects that practice skills like breaking down a project into classes, online or offline. The point is, practice these problems here to make sure you know the rules, but consider projects on your own as well.

Directions

In these problems, you will create your own classes and move variables and actions into them to practice. You will encounter issues of scope, issues of instantiation, and issues related to actions inside of classes. As before with these Parsons problems, you can drag and drop, use the keyboard, or even just write in the editor the solution to the problem and run the code. As a reminder, the hotkey to run the code is ALT + SHIFT + R on Windows and CTRL + SHIFT + R on Mac.

  1. Learn about Classes

Wrap up

Imagine a computer game you might create, which is a good example for classes. If you had such a game, how would you organize all the pieces in the game?

Next Tutorial

In the next tutorial, we will discuss Apps2 Online, which describes how to make your own apps with behaviors.