Topic 3: Introduction to Object-Oriented Programming in Java

What is object-oriented programming?

So far, you have met procedural programming. Procedural programming involves statements sequentially executing one after the other, with common tasks (such as, for example, calculating the cube of a number or printing a character a certain number of times) placed in functions.

However, once programs become larger, our programs can become harder to read and maintain, even if we use functions to accomplish common tasks. Therefore, another approach is needed and this is where object-oriented programming comes in. Object-oriented programming involves creating code to represent real world entities, such as cats, employees, students or graphical user interface elements. An object-oriented program will then contain several objects - code representations of these real-world entities - all communicating with each other.

Classes and Objects

When doing object-oriented programming, we need to distinguish between classes and objects. What is the difference between a class and an object?

Attributes and methods

Classes contain two components: attributes and methods.

Example

A Cat class

Here is an example of a Java class representing a Cat:

public class Cat
{
    private String name;
    private int age, weight;
    
    public Cat (String nameIn, int ageIn, int weightIn)
    {
        this.name = nameIn;
        this.age = ageIn;
        this.weight = weightIn;
    }
    
    public void walk()
    {
        this.weight--;
    }

    public void display()
    {
        System.out.println("Name: " + this.name + " Age: " + this.age + " Weight: " + this.weight);
    }
}
So what does this code mean?
public class Cat
This line states that we are creating a class called Cat. Remember that a class is a blueprint or specification for all objects of that type. So the class will not actually create an individual, specific Cat, but instead, describes what Cats are and how they operate.

private String name;
This line is defining an attribute called name. The line is saying that each Cat object created using this class will have their own name attribute, representing their name. We will come on to the meaning of the keyword private a bit later.

private int age, weight;
This line does the same for the age and the weight, which are both integers.

public Cat (String nameIn, int ageIn, int weightIn)
{
    this.name = nameIn;
    this.age = ageIn;
    this.weight = weightIn;
}
This piece of code is called a CONSTRUCTOR. A constructor is a special method (see above) which is used to initialise objects of the current class. A constructor has the same name as the class, so this one is called "Cat". (We will see the meaning of public later). When we create an object (and you will see how to do this below) the constructor is called. This constructor takes three parameters from outside the class (nameIn, ageIn and weightIn) and sets the attributes to the parameters passed in. Note the difference between attributes and parameters: Note also the use of the keyword this to represent the attributes. this represents the current object we are working with. So the code will set the attributes of whichever object we're initialising to the parameters passed in.

(this is actually optional here, but I have included it for clarity).

    
public void walk()
{
    this.weight--;
}
This is a method, which, as we saw above, is an action or something that objects of a class can do. The method is called walk(). The effect of this method is to walk a cat by reducing the cat's weight (this.weight) by one. This type of code probably looks familiar to you from Introduction to Programming and Problem Solving as a function. However, it is a bit different to a normal function. It lives inside our class (i.e. the Cat class). This basically means that it will operate on objects belonging to the Cat class. So, a method can be defined as a function which belongs to a class.

public void display()
{
    System.out.println("Name: " + this.name + " Age: " + this.age + " Weight: " + this.weight)
}
This code defines another method called display() which displays the details of the cat.

Creating objects of the Cat class

I cannot emphasise strongly enough that the above code does not actually create any specific Cat objects. It merely defines a Cat class, which is a blueprint or specification for what Cats are and what they do. We need, in addition, to create specific Cat objects in our main() (or elsewhere outside the Cat class). Here is a main() which creates two Cat objects and does things with them:

public class CatApp
{
    public static void main (String[] args)
    {
        Cat tom = new Cat ("Tom", 5, 15);
        Cat tigger =new Cat ("Tigger", 10, 5);
        
        tom.display();
        tigger.display();
        
        tom.walk();
        tigger.walk();
        
        tom.display();
        tigger.display();
        
        tom.walk();
        tom.display();
    }
}
How is this code working?
Cat tom = new Cat ("Tom", 5, 15);
Cat tigger =new Cat ("Tigger", 10, 5);
These two lines create two specific Cat objects, tom and tigger. Note the keyword new. This means that we are creating a new object of the specified class (Cat here). Note also how we pass into the object three pieces of information: the name (e.g. "Tom"), the age (e.g. 5), and the weight (e.g. 15). These three pieces of information become the parameters in the constructor. So if we revisit the constructor:
public Cat (String nameIn, int ageIn, int weightIn)
{
    this.name = nameIn;
    this.age = ageIn;
    this.weight = weightIn;
}    
When we create our first Cat, nameIn takes the value "Tom", ageIn takes the value 5, and weightIn takes the value 15. Since the constructor then sets the attributes to these three parameters, the name, age and weight attributes of the object tom will be "Tom", 5, and 15 respectively. So when we display the object tom:
tom.display();
then the display() method will be called, which, if you remember, is as follows:
public void display()
{
    System.out.println("Name: " + this.name + " Age: " + this.age + " Weight: " + this.weight)
}
Since the display() method displays the name, age and weight attributes, which we set in the constructor, the display() method will output:
Name: Tom Age: 5 Weight: 15

Likewise for the second cat, we will set up a cat with a name attribute of "Tigger", an age attribute of 10 and a weight attribute of 15, so that when we display Tigger we end up with:

Name: Tigger Age: 10 Weight 5

Having displayed the cats, we then walk() them:

tom.walk();
tigger.walk();
These two lines will call the walk() method on tom and tigger. Since the effect of the walk() method is to reduce the weight attribute of the current cat by one, when we display() the two cats again, their weight will be reduced by one. We then walk() Tom again so Tom's weight will be reduced by a further unit.

So the overall output of the program will be:

Name: Tom Age: 5 Weight: 15
Name: Tigger Age: 10 Weight 5
Name: Tom Age: 5 Weight: 14
Name: Tigger Age: 10 Weight 4
Name: Tom Age: 5 Weight: 13

Exercise

  1. Add an additional method called eat() to the Cat class. The eat() method should add one to the weight of the cat.
  2. Create a new main() with two Cats with these attributes:
    Name: Felix Age:2 Weight:7
    Name: Sylvester Age:7 Weight:10
    Make Felix eat twice, and display Felix's details. Make Sylvester walk four times, and display Sylvester's details.
  3. Create a completely new class called Hero to represent a hero in a 2D game. Give it the following attributes: Also give it the following methods.
  4. Create a main() which creates a Hero object, calls the methods a few times, and prints the hero's details after each method to prove that the Hero's properties have changed. (Later on, you will actually create a simple chase game making use of this Hero class!)