Object-Oriented Programming Foundations

Introduction to Object-Oriented Design

ReadingPreview

You are viewing a free preview lesson.

Lesson Overview

Object-Oriented Programming, or OOP, is not simply about creating classes, making fields private, or writing getters and setters.

OOP is an approach to organizing and modeling a program through meaningful objects.

An object generally has:

  • State
  • Behavior
  • Identity
  • A clear responsibility

In a small program, it is possible to keep all data and logic inside the main() method.

public class Main {

    public static void main(String[] args) {
        String learnerName =
                "Nur";

        int completedLessons =
                16;

        int totalLessons =
                20;

        double progress =
                completedLessons
                * 100.0
                / totalLessons;

        System.out.println(
                learnerName
                + " completed "
                + progress
                + "% of the course."
        );
    }
}

This code is simple and readable.

However, as an application grows, we may need to handle:

Learners
Courses
Lessons
Enrollments
Progress
Payments
Assessments
Certificates

If we keep adding more variables and conditions, the code becomes difficult to manage.

OOP helps us organize related state and behavior into meaningful units.

Learning Objectives

After completing this lesson, you will be able to:

  • Explain the purpose of OOP
  • Understand the conceptual difference between a class and an object
  • Identify state, behavior, and identity
  • Understand object responsibility
  • Understand the difference between procedural and object-oriented thinking
  • Identify possible objects from a simple requirement
  • Recognize the basic purpose of encapsulation, abstraction, inheritance, and polymorphism
  • Avoid common beginner OOP misconceptions

Why Do We Need OOP?

Suppose we are building a learning platform.

A learner has enrolled in a course.

We need to track:

Learner name
Course title
Completed lessons
Total lessons
Enrollment status

For one learner, keeping separate variables is easy:

String learnerName =
        "Nur";

String courseTitle =
        "Java and OOP Foundation";

int completedLessons =
        16;

int totalLessons =
        20;

boolean enrollmentActive =
        true;

However, with multiple learners and courses, this approach quickly becomes messy.

Example:

String firstLearnerName =
        "Nur";

int firstCompletedLessons =
        16;

String secondLearnerName =
        "Sakib";

int secondCompletedLessons =
        18;

As an application grows, problems may include:

  • Related values becoming separated
  • Updating the wrong learner's data
  • Duplicating the same rule in multiple places
  • Rewriting the same calculation repeatedly
  • Difficulty understanding which code is responsible for which business concept

OOP helps us think in terms of separate concepts:

Learner
Course
Enrollment

Procedural Thinking vs. Object-Oriented Thinking

Procedural thinking usually asks:

What steps need to be executed?

Example:

1. Read completed lessons
2. Read total lessons
3. Calculate progress
4. Print the result

Object-oriented thinking asks:

Which object owns this data, and which object should be responsible for this behavior?

Example:

Enrollment
- Knows completed lessons
- Knows total lessons
- Calculates progress
- Updates progress

Neither approach is always better.

For a small calculation, procedural code may be simpler.

But when related state, rules, and behavior grow, object-oriented organization becomes useful.

What Is an Object?

An object is a specific entity in a program.

Three important characteristics of an object are:

State
Behavior
Identity

State

State is the object's current data.

An enrollment's state might be:

Learner: Nur
Course: Java and OOP Foundation
Completed lessons: 16
Total lessons: 20
Status: Active

State can change.

Before:

Completed lessons: 16

After completing another lesson:

Completed lessons: 17

Behavior

Behavior represents meaningful actions an object can perform.

Possible enrollment behavior:

Complete a lesson
Calculate progress
Cancel enrollment
Check whether the course is completed

In Java, behavior is represented using methods.

Conceptually:

enrollment.completeLesson();

enrollment.calculateProgress();

enrollment.cancel();

Identity

Identity helps distinguish which specific object we are working with.

Two enrollments may have the same state:

Completed lessons: 10
Total lessons: 20

but still be different enrollments.

Example:

Nur → Java
Sakib → Java

Even if both have the same progress, they are not the same enrollment.

This distinction is identity.

What Is a Class?

A class is a custom type that defines the structure and behavior of objects.

Conceptually:

Class:
Enrollment

Objects:
Nur's Java enrollment
Sakib's Java enrollment
Jalisa's Backend enrollment

A class can define:

  • What data an object stores
  • What behavior is available
  • How state can change

A class is not a specific object.

It is the definition for objects of that type.

Class vs. Object

ClassObject
Type or definitionActual instance
Defines state structureHolds actual state values
Defines behaviorExecutes behavior
CourseA specific course object
EnrollmentA specific enrollment object

Conceptual Java:

Course javaCourse =
        new Course();

Enrollment nurEnrollment =
        new Enrollment();

Here:

Course
Enrollment

are classes.

And:

javaCourse
nurEnrollment

are references to objects.

We will study this syntax in detail in the next lesson.

Responsibility

One of the most useful questions in OOP design is:

Which object should be responsible for which task?

Suppose we need to calculate progress.

Possible owners:

Learner
Course
Enrollment
Main

A learner can have different progress in different courses.

Nur
Java    → 80%
Backend → 40%

Therefore, progress is not simply learner data.

A course can also have different progress for different learners.

Java
Nur   → 80%
Sakib → 90%

Therefore, progress is not simply course data either.

Progress is part of the relationship between:

Learner
+
Course

So Enrollment can be a natural owner of progress.

Conceptually:

enrollment.calculateProgress();

Modeling Simple Concepts

Possible objects in a learning platform might include:

Learner
Course
Lesson
Enrollment
Payment

Each concept can have a different responsibility.

Learner

Possible state:

Name
Email
Account status

Possible behavior:

Update profile
Deactivate account

Course

Possible state:

Title
Price
Publication status

Possible behavior:

Publish
Change price

Enrollment

Possible state:

Learner
Course
Completed lessons
Status

Possible behavior:

Complete lesson
Calculate progress
Cancel enrollment

Keeping State and Behavior Together

Suppose:

int completedLessons =
        20;

int totalLessons =
        18;

Both values are individually valid int values.

But together, the state is suspicious:

Completed lessons > total lessons

If an object owns this state, its related behavior can enforce the rule whenever the state changes.

Conceptually:

enrollment.completeLesson();

The method can decide whether another lesson is allowed to be completed.

This is stronger design than uncontrolled mutation.

A useful OOP idea is:

The object that owns state can use its behavior to protect the rules of that state.

OOP Is Not Only About Grouping Data

This class groups related data:

public class Enrollment {

    String learnerName;
    String courseTitle;
    int completedLessons;
    int totalLessons;
}

That is a useful beginning.

But OOP does not end there.

If any code can write:

enrollment.completedLessons =
        -10;

then the object is not protecting its own state.

Later, we will use meaningful methods and controlled access.

Example:

enrollment.completeLesson();

Encapsulation — Preview

The basic idea of encapsulation is:

Keep related state and behavior together, and control how state is accessed or modified.

Example:

course.changePrice(
        4990
);

The method can check whether the price is valid.

Encapsulation is not simply:

private fields
+
getter
+
setter

Meaningful behavior and protecting valid state are more important.

We will implement encapsulation in a dedicated lesson.

Abstraction — Preview

Abstraction exposes meaningful operations to the caller while hiding unnecessary internal details.

Example:

course.publish();

The caller only needs to know:

Publish the course

How the internal implementation works is not the caller's concern.

The goal of abstraction is:

Clear intent, fewer unnecessary details.

Inheritance — Preview

Inheritance allows one type to extend the structure or behavior of another type.

Conceptual example:

User
├── Learner
└── Instructor

Inheritance can be useful, but it is not the starting point for learning OOP.

We will study inheritance in detail after classes and objects are clear.

Polymorphism — Preview

Polymorphism allows different implementations of the same common operation.

Conceptually:

EmailNotification
SmsNotification
PushNotification

All of them might support an operation such as:

send();

but each type can behave differently.

We will study this in more detail later.

Four Ideas at a Glance

At this stage, remember only the high-level purpose:

Encapsulation
→ protect state and rules

Abstraction
→ hide unnecessary details

Inheritance
→ inherited relationships between related types

Polymorphism
→ same operation, different implementations

For now, understanding the foundation of classes and objects is more important than memorizing these terms.

A First OOP Preview

The following code is only a preview:

public class Enrollment {

    String learnerName;
    int completedLessons;
    int totalLessons;

    void completeLesson() {
        if (
                completedLessons
                >= totalLessons
        ) {
            return;
        }

        completedLessons++;
    }

    double calculateProgress() {
        if (totalLessons == 0) {
            return 0.0;
        }

        return completedLessons
                * 100.0
                / totalLessons;
    }
}

Usage:

Enrollment enrollment =
        new Enrollment();

enrollment.learnerName =
        "Nur";

enrollment.completedLessons =
        16;

enrollment.totalLessons =
        20;

enrollment.completeLesson();

System.out.println(
        enrollment.calculateProgress()
);

Output:

85.0

You do not need to memorize the entire code yet.

For now, observe:

Enrollment object
↓
owns enrollment state
↓
provides enrollment behavior

This Design Is Not Complete Yet

We are still directly writing:

enrollment.completedLessons =
        16;

Later, we will see why limiting direct field mutation can be useful.

In upcoming lessons, we will improve this model through:

Classes and objects
Fields and methods
Constructors
Encapsulation
Composition
Immutability

Not Every Problem Needs OOP

A simple calculation:

static int add(
        int first,
        int second
) {
    return first + second;
}

does not need a new class hierarchy.

OOP is more useful when a program contains:

  • Related state
  • Rules
  • Multiple entities
  • Changing state
  • Relationships
  • Meaningful responsibilities

The right tool depends on the problem.

Common Beginner Misconceptions

OOP Means Many Classes

No.

More classes do not automatically create better design.

A class is meaningful when it represents a coherent concept or responsibility.

OOP Means Getters and Setters

No.

setPrice(-500);

If an invalid price is accepted, a mechanical setter does not improve the design.

The goal of encapsulation is to protect state.

Every Noun in a Requirement Must Become a Class

No.

Requirement:

Course title

Here, Course may become a class.

But title may simply be a:

String

field.

OOP Replaces Loops and Conditions

No.

Methods inside objects will still contain:

Variables
Conditions
Loops
Calculations
Algorithms

OOP does not replace fundamental programming logic.

Inheritance Is the Main Goal of OOP

No.

Inheritance is one feature of OOP.

But clear responsibilities, encapsulation, and object relationships are more fundamental.

Identifying Objects from a Requirement

Requirement:

Nur enrolls in a Java course and completes lessons.

Possible concepts:

Learner
Course
Enrollment
Lesson

Step 1: Identify Important Concepts

Ask:

What meaningful things is the program working with?

Possible:

Learner
Course
Enrollment

Step 2: Identify State

Example:

Learner
- name
- email

Course
- title
- lesson count

Enrollment
- learner
- course
- completed lessons
- status

Step 3: Identify Behavior

Course
- publish

Enrollment
- complete lesson
- calculate progress
- cancel

Step 4: Assign Responsibility

Ask:

Who owns this data?

Who should perform this action?

Who should enforce this rule?

Examples:

Course title
→ Course

Learner email
→ Learner

Enrollment progress
→ Enrollment

Step 5: Think About Invalid States

Examples:

Blank course title

Negative price

Completed lessons greater than total lessons

For now, simply identify invalid states.

Later, we will learn how to prevent them using constructors and methods.

Practice Exercise 1: State and Behavior

For the Course concept, write:

  • Four pieces of state
  • Three possible behaviors

Practice Exercise 2: Choose the Owner

Identify the natural owner of the following data:

Learner email
Course title
Enrollment progress
Lesson duration
Payment status

Choose from:

Learner
Course
Enrollment
Lesson
Payment

Practice Exercise 3: Model an Enrollment

Do not write code.

Conceptually define:

State
Behavior
Possible invalid states

Practice Exercise 4: Procedural or Object-Oriented?

Explain which approach may be simpler for each problem:

  1. Add two numbers
  2. Manage course enrollment progress and cancellation
  3. Convert Celsius to Fahrenheit
  4. Manage account balance and withdrawal rules

Practice Exercise 5: Responsibility Problem

Consider:

public class Application {

    String learnerName;
    String courseTitle;
    long paymentAmount;
    int completedLessons;

    void publishCourse() {
    }

    void processPayment() {
    }

    void completeLesson() {
    }
}

What is the design problem with this class?

Identify possible focused concepts.

Practice Exercise 6: Invalid States

Enrollment state:

completedLessons
totalLessons
active

Identify at least three invalid or suspicious states.

Knowledge Check

Question 1

What is the basic purpose of OOP?

Question 2

What are three important characteristics of an object?

Question 3

What is state?

Question 4

What is behavior?

Question 5

What is identity?

Question 6

What is the difference between a class and an object?

Question 7

What does object responsibility mean?

Question 8

Why might progress be the responsibility of Enrollment?

Question 9

What is the basic purpose of encapsulation?

Question 10

What does abstraction do?

Question 11

What is the basic idea of inheritance?

Question 12

What is the basic idea of polymorphism?

Question 13

Is OOP the best solution for every problem?

Question 14

Why is it useful to identify invalid states early?

Knowledge Check Answers

Answer 1

To organize related state, behavior, and responsibilities into meaningful objects.

Answer 2

State
Behavior
Identity

Answer 3

The current data of an object.

Answer 4

Meaningful actions the object can perform.

Answer 5

The concept that distinguishes which specific object we are working with.

Answer 6

A class is a type or definition. An object is an actual instance of that class.

Answer 7

It describes which object should own particular data, perform particular behavior, and protect particular rules.

Answer 8

Because progress belongs to the relationship between a specific learner and a specific course.

Answer 9

To keep state and related behavior together and control how state is accessed or changed.

Answer 10

It exposes meaningful operations to callers while hiding unnecessary implementation details.

Answer 11

A type can inherit structure or behavior from another related type.

Answer 12

Different types can implement the same common operation differently.

Answer 13

No. A simple calculation or short procedural workflow may often be simpler.

Answer 14

It helps determine which rules constructors and methods should enforce later.

Lesson Summary

In this lesson, we learned:

  • OOP is not only class syntax
  • OOP is an approach to organizing state, behavior, and responsibilities
  • Objects have state, behavior, and identity
  • A class is the type or definition of an object
  • An object is an actual instance of a class
  • Procedural thinking focuses on steps
  • Object-oriented thinking focuses on ownership and responsibility
  • Keeping related state and behavior in the same object can be useful
  • An object can protect the rules of its own state
  • Encapsulation helps control state access and modification
  • Abstraction hides unnecessary details
  • Inheritance can model relationships between related types
  • Polymorphism supports different implementations of the same operation
  • OOP does not mean creating many classes or writing getters and setters
  • Not every noun in a requirement needs to become a class
  • OOP does not replace loops, conditions, or algorithms
  • Good modeling begins by identifying concepts, state, behavior, responsibility, and invalid states