Lesson 11 — OOP Foundations

Classes and Objects

Object-Oriented Programming models software as a collection of objects — each with its own data and behaviour. Java is built entirely around this idea. Mastering it unlocks the full power of the language.

The Core Idea: Modelling the World

Before Java and OOP, programs were written as long sequences of instructions operating on separate data. As programs grew larger, this became unmaintainable. OOP solves this by grouping related data and behaviour together into a single unit — the object.

A class is the blueprint — a description of what an object will look like and what it can do. An object is a specific instance of that blueprint created in memory at runtime. You can create thousands of objects from one class, each holding its own data.

Defining a Class

A class contains fields (the data — what the object has) and methods (the behaviour — what the object can do).

JAVA — Learner class
public class Learner {

    // Fields — the data each Learner object holds
    String  fullName;
    int     age;
    String  course;
    double  averageMark;
    boolean isActive;

    // Method — behaviour: what a Learner can do
    public void introduce() {
        System.out.println("Hello! I am " + fullName +
            ", studying " + course + " at Your IT Tutor.");
    }

    public void printReport() {
        System.out.println("--- Learner Report ---");
        System.out.println("Name:    " + fullName);
        System.out.println("Age:     " + age);
        System.out.println("Course:  " + course);
        System.out.printf ("Average: %.1f%%%n", averageMark);
        System.out.println("Active:  " + isActive);
    }

    public String getGradeLabel() {
        if (averageMark >= 80) return "Distinction";
        if (averageMark >= 60) return "Merit";
        if (averageMark >= 50) return "Pass";
        return "Not yet competent";
    }

}

Creating and Using Objects

The new keyword allocates memory for an object and initialises it. After creating an object, you access its fields and methods using the dot operator (.).

JAVA — Creating objects
public class Main {
    public static void main(String[] args) {

        // Create two Learner objects — each has its own copy of the fields
        Learner learner1 = new Learner();
        learner1.fullName    = "Thandi Mokoena";
        learner1.age         = 21;
        learner1.course      = "Java";
        learner1.averageMark = 74.5;
        learner1.isActive    = true;

        Learner learner2 = new Learner();
        learner2.fullName    = "Sipho Dlamini";
        learner2.age         = 24;
        learner2.course      = "Python";
        learner2.averageMark = 81.0;
        learner2.isActive    = true;

        // Call methods on each object — each uses its own data
        learner1.introduce();
        learner2.introduce();

        System.out.println();

        learner1.printReport();
        System.out.println("Grade: " + learner1.getGradeLabel());

        System.out.println();

        learner2.printReport();
        System.out.println("Grade: " + learner2.getGradeLabel());

    }
}

Objects in Arrays

You can store multiple objects in an array, then loop through them — a very common pattern in real programs.

JAVA — Objects in arrays
Learner[] cohort = new Learner[3];

cohort[0] = new Learner();
cohort[0].fullName = "Lerato"; cohort[0].averageMark = 68.0; cohort[0].course = "SQL";

cohort[1] = new Learner();
cohort[1].fullName = "Bongani"; cohort[1].averageMark = 88.5; cohort[1].course = "C#";

cohort[2] = new Learner();
cohort[2].fullName = "Zanele"; cohort[2].averageMark = 55.0; cohort[2].course = "Java";

// Process all learners
double cohortTotal = 0;
for (Learner l : cohort) {
    System.out.printf("%-10s | %s | %s%n",
        l.fullName, l.course, l.getGradeLabel());
    cohortTotal += l.averageMark;
}
System.out.printf("Cohort average: %.1f%%%n", cohortTotal / cohort.length);

The null Reference

Before you assign an object to a variable, it holds null — the absence of an object. Trying to call a method on a null reference causes a NullPointerException — the most common runtime error in Java.

JAVA
Learner l = null; // l points to nothing

// This will throw NullPointerException:
// l.introduce();

// Safe pattern — always check before using
if (l != null) {
    l.introduce();
} else {
    System.out.println("No learner assigned.");
}Null safety

Practice Task

Your Turn

Design and implement a BankAccount class with fields: accountNumber (String), holderName (String), balance (double), and isActive (boolean). Add methods: deposit(double amount) — adds to balance if positive, withdraw(double amount) — subtracts if sufficient funds exist (print a message if not), printStatement() — prints all fields formatted. Create three accounts in main, perform deposits and withdrawals on each, and print their statements.

Common Mistakes

  • Forgetting new: Learner l = Learner(); is a compile error — new is required.
  • Calling a method on a null reference — always initialise objects before using them.
  • Accessing fields directly from outside the class (we address this with encapsulation in Lesson 13) — for now it works, but it is not professional practice.
  • Confusing the class and the object — the class is the blueprint (written once), the object is the instance (created with new).
  • One class trying to do everything — each class should model one concept. A Learner class should not also handle file writing.

Professional Tip

When you design a class, ask: what data does this thing hold, and what operations make sense for it? A class name should be a noun (Learner, Account), a method name should be a verb (introduce, deposit).

Mini Quiz

What does the new keyword do in Java?