The Coder's Handbook   

Object Oriented Programming

OBJECTS AND CLASSES

Object Oriented Programming

Java is a programming language that is built on the concept of Object Oriented Programming (OOP).  This means that your program is designed as a series of classes that we instantiate as objects.  Your code is about a series of objects that interact, rather than actions that simply happen in a fixed order.


We can contrast this with other programming paradigms:



Objects vs. Classes


It is important to remember the difference between these two terms:


Each object is simply an instance of a class.  We take this abstract concept and make an actual object in the world.  You can have many objects that share a single class.

 

The class defines the categories of data holds, but the data itself will vary from object to object.

CONSIDER AN EXAMPLE...

We will break down this full example over time.  Read it over to get a big picture, then get into the details in each section.

 Example - Chess Board

code:

public class Main

{

     public static void main(String[] args)

     { 

          Knight whiteQueensKnight = new Knight(“White”, ‘B’, 1);

          Knight blackQueensKnight = new Knight(“Black”, ‘B’, 8);


          whiteQueensKnight.printLocation(); 

          whiteQueensKnight.move(‘C’, 3); 


          blackQueensKnight.printLocation(); 

          blackQueensKnight.move(‘A’, 6); 

  

     }

}

code:

public class Knight

{

// Instance Fields (aka Class Level Variables)

private String color;

private char letter;

private int number;  


// Constructor

public Knight(String color, char letter, int  number)  

{

   this.color = color;        

   this.letter = letter;

   this.number = number;

}

public void printLocation()

{  

   System.out.println(color + “ Knight at: “ + letter + number);

}

public void move(char newLetter, int newNumber)

{

   letter = newLetter;

   number = newNumber;

   System.out.println(color + “ Knight to: “ + letter + number);

   }  

}

 Example #1 - Chess Bo


We could represent an entire chess game with a program like this without displaying an actual grid, simply by using the coordinate system that is used to record chess moves. 

In a more robust implementation, the move() method would check if a move is legal.  Right now, a Knight could just teleport anywhere.


output:

White Knight at B1

Black Knight at B8

White Knight to C3

Black Knight to A6

SCOPE, CONSTRUCTORS, AND THIS

Scope and Instance Fields

An instance field is a variable that is stored within a class.  Each instance of the class (that is, each object) has its own copy of this data.  It is more casually called a class-level variable.   


That means its scope is limited to the class, but it can be accessed by any method inside the class.  We'll talk about the word private in the next section.


What is a constructor?

A constructor is a special method which is called when you instantiate a class using the new operator.  It is responsible for "setting up" the object.  


A constructor might not have any parameters.  In this case, you might have an object with preset or random starting data.  An object often takes some sort of information when it is created to configure it.  We've seen this already with Scanner.  You can set it up for console input (System.in) or to read input from a file.

Ambiguity and This

Sometimes you'll have two variables with the same name.  When this happens, Java always assumes you are referring to the one with the most local scope.


You can always specifically refer to an object by saying the keyword this.  It essentially just means "me."  Then you can use the dot operator to refer to the object's variables and methods.


In the Knight constructor, we use this to assign the each parameter to its corresponding instance field. 


An alternate way of avoiding this ambiguity is simply to avoid repeating variable names.   Consider the second version of the constructor.  


You're welcome to use either approach, but you should get comfortable with using this in either case.

code:

public class Main

{

     public static void main(String[] args)

     { 

          Knight whiteQueensKnight = new Knight(“White”, ‘B’, 1);

          Knight blackQueensKnight = new Knight(“Black”, ‘B’, 8);  

     }

}

public class Knight

{

// Instance Fields (aka Class Level Variables)

private String color;

private char letter;

private int number;  


// Constructor

public Knight(String color, char letter, int  number)  

{

   this.color = color;        

   this.letter = letter;

   this.number = number;

}

// Alternate version of constructor

public Knight(String c, char l, int  n)  

{

   this.color = c;        

   this.letter = l;

   this.number = n;

}

PUBLIC AND PRIVATE

Access Modifiers

An access modifier (aka access specifier) identifies who can access a variable or method.   By default, they have package level access. - meaning it is shared by classes that live in the same folder.


We'll make this more complicated later, but for now you will need to specify every class, method, and variable as being public or private.


Public

When something is public, anyone can access it.  This makes sense for methods, which need to be called by the outside world. 


As you get more experience you'll learn when to break this rule.  For instance, maybe you wrote a helper method that isn't useful outside of a class.   Then we'd make it private.

Private

We need to be careful and not let everything be accessed by just anyone.  Private methods and data can only be accessed within the class.


Imagine you had a very large program with millions of pieces of data - and if one is changed incorrectly, you have a runtime error.  It is critical to silo those variables so we can track down where bugs emerge.


Next, we'll learn how to use methods to allow outside code to interact with our data.

You will learn more about protected once we study inheritance.

public class Knight

{

// We make our data private (always)

private String color;

private char letter;

private int number;  


// We make our methods public (usually)

public void printLocation()

{  

   System.out.println(color + “ Knight at: “ + letter + number);

}

}

Divide your code up like bulwarks in a ship.  If each class is sealed up tight, your whole program won't get flooded with bugs.

GETTING TO THE DATA

Types of Methods
When we write programs, every method is either an accessor or a mutator.

Accessor methods simply retrieve information, but do not change the state of the program

Mutator methods change the program.  They typically do not return a value.  For example:

Accessors and "Getters"

Since our data is private, we'll need to write an accessor to let the user read the data but not modify it.  A getter is a basic accessor method: it simply returns the value of an instance field. 

code:

void getCurHealth()
{
  return curHealth;
}


These are extremely common.  Get used to writing these!



No, not that kind of mutator.  They're not even in the MCU yet!

Mutators and "Setters"


On the flip side, we can control how the data is changed through mutator methods.  A setter is a basic mutator method: it simply assigns the value you pass to the matching instance field.  But often we prefer to restrict or limit how someone can modify our data to avoid errors.  Consider two examples:

code:

void setHealth(int amount)
{
   curHealth = amount;
}

code:

void takeDamage(int amount)
{
    curHealth  -= amount;
    if(curHealth < 0)
    {
        curHealth = 0;
    }
}

The method setHealth is more flexible than takeDamage, but also offers less protection.  You can avoid a lot of problems by managing how the data in each part of your program is modified.

STATIC

Does it belong to the class or the object?


When we design our programs in an object oriented way, most of the time we want each object to have its own instance of data or methods.  For example, if I made a Student class - we'd want each Student object to have their own grade.  That's how it works normally.


private int myGrade;


However, if I put the word static in front of this data, it would be a property of the class and not the object.  This means two things.  First, you access it through the class, rather than the object.  Second, there's only one grade shared by all students.


private static int myGrade;


This seems like a very silly thing to do.  So when WOULD you want to use static?

 

1 - Global Constants


Hopefully by now we understand that making all your data global is dangerous!  If any line of code can change a variable, it's hard to know where problems arise.  But that isn't an issue for a constant.  If it is impossible to change the data, it's usually okay to make that information publicly available. 


You see this in placed like Slick2D's color class, which lets you say things like Color.CYAN.  CYAN is just a constant that stores a specific RGB value for your convenience. 

class Color {
    public static Color CYAN = new Color(0, 255, 255);
}


Or in Hivemind, you'll see constants like Values.RAIDER_ATTACK_COOLDOWN which tells you that unit's attack speed.


class Values {
    public static int RAIDER_ATTACK_COOLDOWN = 60;
}

 

This object is global and static, but I'm pretty sure it isn't constant.

 

Sometimes we don't need to create a Calculator object to get things done.  Instead, we directly ask the class - The True Form of Mathematics itself.  That sounds way cooler.

2 - Utility Functions


Sometimes you'll write code that is just a harmless handy helper.  It's a tool and it'd be very silly to have to use it in a proper object oriented fashion.  An example of this you have encountered is the Math class.


You don't need to declare and initialize a Math object named mathDude, then ask mathDude to get you a random number or find a minimmum value.  You just ask the Math class to do it for you!   To do this you simply make a static method.  For instance:


class Math {
    public static int min(int a, int b) {
        if(a <= b) return a;
        else return b;
    }
}  

3 - Main


At the start of the course I promised with time you'd understand the line:


public static void main(String[] args)


Well, you're there.  The main method takes in a String[] as arguments from the operating system (you won't use them).  It is public and returns no values.  And finally, it's static.  That means it isn't part of some Main object... it's just a part of the class itself. 


This is why if you write loose methods in the Main class you'll need to make them static too.   This can spread like a plague. 


To solve this, avoid putting a lot of code into the class containing main.  Just use it to kick off your program and do the heavy lifting in another class.

 

4 - Singleton Pattern


Sometimes you'll write a class which is intended to only have one object that belongs to it.  Consider classes named things like GameEngine, UserInterface, or CombatGrid.   There is a design pattern called the Singleton Pattern where you build your code around this knowledge.


In these cases, you might even make everything in this class static rather than pretending that it is object oriented.  For example, in Hivemind, Mr. M's team has a class which coordinates which Miner units reserve and harvest asteroids.  The MiningManager class largely consists of static methods and data.


This is an advanced case, and it won't come up on the AP Exam.  But it's worth remembering when you start building your own large projects.

RESOURCES

Coding With John - Constructors

Coding With John - This

Coding With John - Static vs. Nonstatic

Alex Lee - Object Oriented Programming

Alex Lee - Constructors

Alex Lee - How to use "this" 

Alex Lee - How to use "static"