CMUQ 15-121 Classes, Objects, and OOP



1. Introduction

While Python includes support for objects, you don’t actually need to use them in order to write a program. Java, however, is fundamentally object oriented. In Java, everything is an object.

Objects allow us to collect data and the actions that operate on that data into one entity.

A class provides the blueprint of what an object should look like. When you want to actually create one, then you create an instance of the class called an object.

Consider the following sample code for the hero in an adventure game. Our hero has two instance variables: hitPoints (the amount of damage the hero can take until death) and an array of items representing the inventory. There are also two methods: getHit that deducts damage from the hit points, and isDead that tells you if the hero is dead.

public class Hero {
    /*
     * This class has two instance variables
     */
    private int hitPoints;
    private Item[] items;
       
    
    /*
     * This class had two methods
     */
    public void getHit(int damage) {
        this.hitPoints -= damage;        
    }
    
    public boolean isDead() {
        if (hitPoints <= 0) {
            return true;
        }
        else {
            return false;
        }
    }
    
}

It is important to note that defining the Hero class does not create an object. This is just the class, the blueprint for a hero. In order to instantiate a hero we need a line like Hero bob = new Hero(). After that line runs, bob is hero object. We create one from blueprint represented by the class.

2. Visibility Modifiers

You may have noticed that in most of the examples so far both methods and instance variables have keywords in front of them like public and private. These keywords impact which code, outside of the object, is allowed to access that item.

2.1. Summary Table

Consider this table summarizing the visibility modifiers:

Modifier Class Package Subclass Everywhere Else
public X X X X
protected X X X
none used X X
private X

2.2. Conventions

There are a few rules about visibility followed by convention (meaning unofficial rules followed by most programmers):

  1. Instance variables should be private. If you need to access them from outside the class code (which is likely) you should write methods to facilitate this.
  2. Methods that will be used from outside the class should be public.
  3. Methods that will only be used inside the class should be private. Usually these are helper methods that you write to assist you when writing the public methods.

3. Constructors

Every class needs at least one constructor. A constructor is a special method that is used by the class to instantiate an object. Typically, the constructor allocates and initializes the instance variables. You can have more than one constructor, as long as the different constructors have different parameters. If you don’t include a constructor, then Java will automatically include a default constructor that does almost nothing.

Remember our hero class from above? Here it is again, this time with some constructors. Either constructor can be used to instantiate an object from the Hero class.

public class Hero {
    /*
     * This class has two instance variables
     */
    private int hitPoints;
    private Item[] items;
       
    /*
     * This class has two constructors
     */
    
    public Hero() {
        this.hitPoints = 10;
        this.items = new Item[10];
    }
    
    public Hero(int hitPoints) {
        this.hitPoints = hitPoints;
        this.items = new Item[10];
    }
    
    /*
     * This class had two additional methods
     */
    public void getHit(int damage) {
        this.hitPoints -= damage;        
    }
    
    public boolean isDead() {
        if (hitPoints <= 0) {
            return true;
        }
        else {
            return false;
        }
    }
    
}

4. Getters and Setters

Given that instance variables should always be set private, what do you do if you need to modify them from outside the object? You create getters and setters. Getters and setters are methods you add to a class specifically to allow for access to instance variables. Consider the following example to allow the direct modification of a Hero’s hit points:

public class Hero {
    /*
     * This class has two instance variables
     */
    private int hitPoints;
    private Item[] items;

    /*
     * This class has two constructors
     */

    public Hero() {
        this.hitPoints = 10;
        this.items = new Item[10];
    }

    public Hero(int hitPoints) {
        this.hitPoints = hitPoints;
        this.items = new Item[10];
    }

    /*
     * A getter and setter for hitPoints
     */
    public int getHitPoints() {
        return hitPoints;
    }

    public void setHitPoints(int hitPoints) {
        this.hitPoints = hitPoints;
    }

    /*
     * This class had two additional methods
     */
    public void getHit(int damage) {
        this.hitPoints -= damage;
    }

    public boolean isDead() {
        if (hitPoints <= 0) {
            return true;
        } else {
            return false;
        }
    }

}

These allow code that is working with a hero object to modify the hitPoints of the Hero. Without providing getters and setters outside code cannot manipulate hitPoints, because it is a private instance variable.

5. Aside: Static

Let’s take a moment to talk about something else you’ve seen so far: static. When a method or instance variable is declared static that means that it is accessible as part of the class itself, not just as part of instantiated objects.

5.1. Static Methods

The most common reason to declare a method static is because you are writing a helper function that is useful outside the class. For example, the Math class provided by Java includes a number of static methods related to mathematics. If you want to take the power of something, you can simply call the pow method of the Math class directly: Math.pow(2,10). You don’t need to instantiate a Math object before calling the method.

5.2. Static Instance Variables

The most common reason to declare an instance variable static is because it is a constant that is useful outside the class. Returning to our Math example, the Math class has a static instance variable called PI that stores the value of the mathematical constant \(\pi\). You can access it using Math.PI without first needing to create an instance of a Math object.

5.3. Main Method

You’ve seen a number of the examples so far include a main method. The main method is a special static method. If you tell Java to execute a class, it searches that class for a main method that is static and calls that. This is how you specify which code should run first in your program.

The main method is always declared static using the following signature:
public static void main(String[] args)