๐ Welcome to Object-Oriented Programming!
Let's find out what OOP is, why it's super important, and why Java is such a great language to learn it with.
Imagine you want to teach a robot to make a sandwich. You'd have to give it step-by-step instructions: get bread, spread peanut butter, put them together. That's basically what programming is โ giving a computer precise instructions so it can do something useful.
But as the tasks get bigger (imagine a robot that runs an entire restaurant!), those instructions get very messy and hard to manage. That's where Object-Oriented Programming saves the day! ๐ฆธ
Think about LEGO bricks. Each brick is a self-contained piece. You can snap them together, take them apart, reuse them, and build enormous things! OOP works the same way โ you build your program out of small, self-contained pieces called objects.
OOP is a way of writing programs where you organize your code around objects. An object is like a mini-robot that:
- Knows certain things (its data/attributes) โ like a dog knows its name and breed
- Can do certain things (its methods/behaviors) โ like a dog can bark, sit, or fetch
Instead of writing one giant list of instructions, you build a bunch of smart objects that work together. This makes your code:
- โ Easier to understand
- โ Easier to fix when something breaks
- โ Easier to reuse in other projects
Encapsulation
Hiding private details, showing only what's needed
Inheritance
Children inherit traits from parents
Polymorphism
One action, many different forms
Abstraction
Show the big picture, hide the complexity
Java is one of the most popular programming languages in the world! Here's why it's perfect for learning OOP:
- Pure OOP โ Java was built from the ground up with OOP in mind
- Used everywhere โ Android apps, banking software, NASA, Minecraft (originally!) all use Java
- Great error messages โ Java tells you clearly when you make a mistake
- Free! โ You can download and use Java for free
// This is your first Java program! // Don't worry about every word yet โ just read it like a story. public class HelloWorld { public static void main(String[] args) { // This line prints a message to the screen System.out.println("Hello! I am learning Java OOP! ๐"); System.out.println("This is going to be awesome!"); } }
๐๏ธ Classes and Objects
A class is the blueprint. An object is the real thing built from that blueprint. Let's build some objects!
Imagine a cookie cutter. The cutter is the class โ it's the template. Every cookie you stamp out is an object. All cookies have the same shape (from the same class), but you can decorate each one differently (each object has its own values)!
A class is a blueprint that describes what an object will look like and what it can do. A class contains:
- Fields (attributes) โ the data the object holds (like a dog's name, age, breed)
- Methods (behaviors) โ the actions the object can perform (like a dog can bark)
// We're creating a blueprint for a Dog public class Dog { // FIELDS โ these are the "facts" about a dog String name; String breed; int age; // METHOD โ this is something a dog can DO void bark() { System.out.println(name + " says: Woof! Woof! ๐"); } void introduce() { System.out.println("Hi! I'm " + name + ", a " + age + "-year-old " + breed + "!"); } }
An object is a real instance of a class. You use the keyword new to create one. Once you create an object, you can set its data and call its methods.
public class Main { public static void main(String[] args) { // Create a Dog object called "myDog" Dog myDog = new Dog(); myDog.name = "Buddy"; myDog.breed = "Golden Retriever"; myDog.age = 3; // Create ANOTHER Dog object โ same blueprint, different dog! Dog friendsDog = new Dog(); friendsDog.name = "Luna"; friendsDog.breed = "Poodle"; friendsDog.age = 5; // Call their methods! myDog.introduce(); // Hi! I'm Buddy, a 3-year-old Golden Retriever! myDog.bark(); // Buddy says: Woof! Woof! ๐ friendsDog.introduce(); // Hi! I'm Luna, a 5-year-old Poodle! friendsDog.bark(); // Luna says: Woof! Woof! ๐ } }
Build a Video Game Character Class
Create a class called GameCharacter with these fields:
String nameint healthint levelString weapon
Add a method showStats() that prints all the character's info. Then create 2 different character objects!
๐ Encapsulation โ Keep Your Secrets Safe!
Encapsulation means bundling data and methods together, and controlling who can access or change that data. It's like putting your stuff in a locked box.
Think of an ATM machine. You can deposit money, check your balance, and withdraw cash โ those are the things the ATM lets you do. But you have NO idea (and no access to) how it works internally. All those complicated bank connections and security systems are hidden from you. That's encapsulation!
Java uses keywords called access modifiers to control who can see and change data:
| Modifier | Who can access it? |
|---|---|
| public | Anyone, from anywhere |
| private | Only code INSIDE this class |
| protected | This class + subclasses |
The golden rule: make fields private and provide public methods to access them safely.
public class BankAccount { // Private โ no one outside can touch this directly! private String ownerName; private double balance; // GETTER โ lets people READ the balance public double getBalance() { return balance; } // SETTER โ lets people ADD money, but with a safety check! public void deposit(double amount) { if (amount > 0) { balance += amount; System.out.println("โ Deposited $" + amount); } else { System.out.println("โ Invalid amount! Can't deposit negative money."); } } public void withdraw(double amount) { if (amount > balance) { System.out.println("โ Not enough money!"); } else { balance -= amount; System.out.println("๐ธ Withdrew $" + amount); } } public String getOwnerName() { return ownerName; } public void setOwnerName(String name) { ownerName = name; } } public class Main { public static void main(String[] args) { BankAccount myAccount = new BankAccount(); myAccount.setOwnerName("Alex"); myAccount.deposit(100.0); // โ Deposited $100.0 myAccount.deposit(-50.0); // โ Invalid amount! myAccount.withdraw(30.0); // ๐ธ Withdrew $30.0 System.out.println("Balance: $" + myAccount.getBalance()); // Balance: $70.0 } }
myAccount.balance = -9999999 and break everything! With private + setters, you control how data changes. You add protection rules!
Build a Student Grade Book
Create a Student class with private fields: name, grade (a number 0โ100). Write:
- A getter
getGrade() - A setter
setGrade(int g)that only allows 0โ100 - A method
getLetterGrade()that returns "A", "B", "C", "D", or "F"
๐ช Inheritance โ Pass It Down!
Inheritance lets a new class reuse and build upon the code of an existing class, just like you inherit traits from your parents!
Think about animals. All animals eat and breathe. But a dog also barks and fetches. A cat also meows and purrs. So "Dog" and "Cat" inherit the basic animal traits and then add their own special ones. In Java, we say Dog and Cat extend Animal!
When a class extends another class, it becomes its "child" or "subclass". The original class is called the "parent" or "superclass". The child automatically gets all the parent's fields and methods!
- Superclass (parent) = the general blueprint
- Subclass (child) = a more specific blueprint
- The keyword
superlets the child talk to the parent
// PARENT CLASS (Superclass) public class Animal { protected String name; protected int age; public void eat() { System.out.println(name + " is eating. ๐"); } public void sleep() { System.out.println(name + " is sleeping. ๐ค"); } } // CHILD CLASS (Subclass) โ Dog inherits from Animal public class Dog extends Animal { private String breed; // Dog's OWN special method public void bark() { System.out.println(name + " says: WOOF WOOF! ๐"); } public void fetch() { System.out.println(name + " is fetching the ball! ๐พ"); } } // ANOTHER CHILD CLASS โ Cat also inherits from Animal public class Cat extends Animal { public void meow() { System.out.println(name + " says: Meow~ ๐บ"); } public void purr() { System.out.println(name + " is purring... purrr ๐ฑ"); } } // Using it all together! public class Main { public static void main(String[] args) { Dog dog = new Dog(); dog.name = "Rex"; dog.eat(); // Inherited from Animal! Rex is eating. ๐ dog.bark(); // Dog's own method. Rex says: WOOF WOOF! ๐ dog.fetch(); // Dog's own method. Rex is fetching the ball! ๐พ Cat cat = new Cat(); cat.name = "Whiskers"; cat.sleep(); // Inherited from Animal! Whiskers is sleeping. ๐ค cat.meow(); // Cat's own method. } }
class Dog extends Animal, Pet. (But we can get around this with interfaces โ coming up in Lesson 8!)
What if a child class wants to do the same thing as the parent, but differently? It can override the parent's method! You use the annotation @Override to make it clear.
public class Animal { public void makeSound() { System.out.println("Some generic animal sound..."); } } public class Dog extends Animal { // Override means "replace the parent's version" @Override public void makeSound() { System.out.println("Woof woof! ๐"); } } public class Cat extends Animal { @Override public void makeSound() { System.out.println("Meow meow! ๐บ"); } }
Build a Video Game with Inheritance
Create a Character parent class with fields: name, health, level, and a method attack(). Then create two subclasses: Warrior (uses a sword โ๏ธ) and Mage (uses magic โจ). Override attack() in each to print a different message!
๐ญ Polymorphism โ Many Forms!
Polymorphism means "many forms." The same method name can behave differently depending on which object calls it. It's one of OOP's superpowers!
Think about the word "speak". If you tell a human to speak, they talk. If you tell a dog to speak, it barks. If you tell a parrot to speak, it squawks. Same command โ totally different results! That's polymorphism.
| Type | When it happens | Also called |
|---|---|---|
| Compile-time | Method overloading โ same name, different parameters | Static polymorphism |
| Runtime | Method overriding โ child replaces parent method | Dynamic polymorphism |
// Same method name, different behavior per object! public class Animal { protected String name; public void makeSound() { System.out.println("..."); } } class Dog extends Animal { @Override public void makeSound() { System.out.println(name + ": WOOF! ๐"); } } class Cat extends Animal { @Override public void makeSound() { System.out.println(name + ": Meow! ๐บ"); } } class Duck extends Animal { @Override public void makeSound() { System.out.println(name + ": Quack! ๐ฆ"); } } public class Main { public static void main(String[] args) { // An ARRAY of Animals โ but some are Dogs, Cats, Ducks! Animal[] animals = new Animal[3]; Dog d = new Dog(); d.name = "Rex"; Cat c = new Cat(); c.name = "Luna"; Duck k = new Duck(); k.name = "Donald"; animals[0] = d; animals[1] = c; animals[2] = k; // One loop โ each animal makes ITS OWN sound! ๐ for (Animal a : animals) { a.makeSound(); } // Output: // Rex: WOOF! ๐ // Luna: Meow! ๐บ // Donald: Quack! ๐ฆ } }
Cow class with its own makeSound(), the loop automatically handles it. No changes needed!
// Same method name, different parameters = overloading! public class Calculator { // Add two integers public int add(int a, int b) { return a + b; } // Add three integers (same name!) public int add(int a, int b, int c) { return a + b + c; } // Add two doubles (same name!) public double add(double a, double b) { return a + b; } } // Java figures out WHICH version to call automatically!
Create a Shape Drawing App
Create a Shape class with a method draw(). Create 3 subclasses: Circle, Square, and Triangle. Each overrides draw() to print something like "Drawing a circle โญ". Then store them all in a Shape[] array and loop through, calling draw() on each!
๐งฉ Abstraction โ Show the Big Picture!
Abstraction means hiding complex details and showing only the essential features. It helps you focus on WHAT something does instead of HOW it does it.
When you drive a car (or watch someone drive), you press the gas pedal to go faster. You don't need to know how the engine, fuel injectors, and crankshaft all work together internally. The car abstracts all that complexity away and gives you a simple interface: steering wheel, gas, brake. That's abstraction!
An abstract class is a class that can't be used to create objects directly โ it's just a template! It can have abstract methods (no body) that subclasses must implement.
- Use keyword
abstractbeforeclass - Abstract methods have no body โ just a declaration
- Subclasses MUST provide implementations for all abstract methods
- You can still have regular methods in abstract classes
// Abstract class โ can't be used to create an object directly! public abstract class Vehicle { protected String brand; protected int speed; // Abstract method โ subclasses MUST implement this public abstract void move(); public abstract void fuelUp(); // Regular method โ already complete! public void showInfo() { System.out.println("Brand: " + brand + " | Speed: " + speed + "km/h"); } } // Car implements the abstract methods public class Car extends Vehicle { @Override public void move() { System.out.println(brand + " car is driving on the road! ๐"); } @Override public void fuelUp() { System.out.println("Filling up with gasoline โฝ"); } } // Boat implements the abstract methods differently public class Boat extends Vehicle { @Override public void move() { System.out.println(brand + " boat is sailing on water! โต"); } @Override public void fuelUp() { System.out.println("Filling up with marine diesel ๐ข๏ธ"); } } public class Main { public static void main(String[] args) { Car car = new Car(); car.brand = "Toyota"; car.speed = 120; car.showInfo(); // Brand: Toyota | Speed: 120km/h car.move(); // Toyota car is driving on the road! ๐ car.fuelUp(); // Filling up with gasoline โฝ } }
Vehicle v = new Vehicle(); โ Java will give you an error! Abstract classes are templates only. You CAN do: Vehicle v = new Car(); โ using a Car object stored as a Vehicle type.
Build an Abstract Phone System
Create an abstract class Phone with fields brand and model, and abstract methods call(String number) and chargeBattery(). Then create two classes: Smartphone and FlipPhone. Each implements the methods differently!
๐ง Constructors โ The Birth of an Object!
A constructor is a special method that runs automatically when you create an object. It's how you "set up" an object with its starting data right from birth!
When a baby is born, they already have some things set: a name, a birth date, eye color. The constructor is like the "birth certificate" โ it's filled out the moment the object is created, giving it its starting values right away!
- It has the same name as the class
- It has no return type (not even void)
- It runs automatically when you write
new ClassName() - You can have multiple constructors with different parameters (overloading!)
public class Student { private String name; private int grade; private String school; // Constructor #1 โ no parameters (default) public Student() { name = "Unknown"; grade = 0; school = "Unknown School"; System.out.println("A new student was created (no info)!"); } // Constructor #2 โ provide name and grade public Student(String studentName, int studentGrade) { name = studentName; grade = studentGrade; school = "Default School"; System.out.println("Student created: " + name); } // Constructor #3 โ full details public Student(String studentName, int studentGrade, String schoolName) { name = studentName; grade = studentGrade; school = schoolName; System.out.println("Student created: " + name + " at " + school); } public void introduce() { System.out.println("Hi! I'm " + name + ", Grade " + grade + " at " + school); } } public class Main { public static void main(String[] args) { // Uses Constructor #1 Student s1 = new Student(); s1.introduce(); // Uses Constructor #2 Student s2 = new Student("Alex", 7); s2.introduce(); // Uses Constructor #3 Student s3 = new Student("Maria", 8, "Oakwood Academy"); s3.introduce(); } }
this keyword
Inside a constructor (or method), this refers to the current object. If your parameter has the same name as a field, use this.name = name to be clear โ "this object's name = the parameter called name."
public class Pizza { private String size; private String topping; // "this.size" = the field, "size" = the parameter public Pizza(String size, String topping) { this.size = size; this.topping = topping; } public void describe() { System.out.println("A " + size + " pizza with " + topping + "! ๐"); } }
Build a Book Library System
Create a Book class with a constructor that takes title, author, and pages. Add a second constructor that only takes title and author (default pages = 100). Add a method describe(). Create 3 book objects using different constructors!
๐งฒ Interfaces โ Signing a Contract!
An interface is like a contract that a class agrees to follow. It lists the methods a class MUST have, without saying how to do them. This solves the "one parent only" limitation!
Think about a USB port. Any device that has a USB connector agrees to the "USB contract" โ specific size, specific pins. A phone, a keyboard, a mouse โ they're all totally different, but they all follow the same USB interface. In Java, classes that implement an interface agree to provide certain methods.
| Interface | Abstract Class | |
|---|---|---|
| Can have fields? | Only constants | Yes |
| Methods with body? | Default methods only | Yes |
| A class can use how many? | Multiple! | Only one |
| Keyword | implements | extends |
// An interface โ defines a "contract" public interface Swimmable { void swim(); // Any class that implements this MUST have swim() } public interface Flyable { void fly(); } public interface Talkable { void talk(); } // Duck can swim AND fly โ implements TWO interfaces! public class Duck implements Swimmable, Flyable { private String name; public Duck(String name) { this.name = name; } @Override public void swim() { System.out.println(name + " is swimming! ๐"); } @Override public void fly() { System.out.println(name + " is flying! ๐ฆ"); } } // Parrot can fly AND talk! public class Parrot implements Flyable, Talkable { private String name; public Parrot(String name) { this.name = name; } @Override public void fly() { System.out.println(name + " is flying! ๐ฆ"); } @Override public void talk() { System.out.println(name + ": Polly wants a cracker! ๐ฆ"); } } public class Main { public static void main(String[] args) { Duck duck = new Duck("Donald"); duck.swim(); // Donald is swimming! ๐ duck.fly(); // Donald is flying! ๐ฆ Parrot parrot = new Parrot("Polly"); parrot.fly(); // Polly is flying! ๐ฆ parrot.talk(); // Polly: Polly wants a cracker! ๐ฆ } }
extend ONE parent class. But it can implement as many interfaces as you want! This gives Java flexibility without the complications of multiple inheritance.
Design a Superhero System
Create interfaces: Flyable, SuperStrong, Invisible. Then create superheroes: Superman (Flyable + SuperStrong), Invisible Woman (Invisible + SuperStrong), Iron Man (Flyable only, but flies with a suit!). Make each implement the interfaces their way!
๐ Build a Zoo Management System!
Bring EVERYTHING you've learned together! You'll build a complete Zoo app using all 4 pillars of OOP plus constructors and interfaces.
- ๐งฉ Abstract class:
Animalwith abstract methodsmakeSound()andfeed() - ๐งฒ Interfaces:
Swimmable,Flyable,Trainable - ๐ช Subclasses:
Lion,Penguin,Eagle,Dolphin - ๐ Encapsulation: Private fields with getters/setters
- ๐ง Constructors: Each animal built with name + age
- ๐ญ Polymorphism: One loop that calls
makeSound()on all animals
// ============================================ // INTERFACES // ============================================ interface Swimmable { void swim(); } interface Flyable { void fly(); } interface Trainable { void performTrick(String trick); } // ============================================ // ABSTRACT CLASS โ the base for all animals // ============================================ abstract class Animal { private String name; private int age; private double weight; // Constructor public Animal(String name, int age, double weight) { this.name = name; this.age = age; this.weight = weight; } // Getters (Encapsulation!) public String getName() { return name; } public int getAge() { return age; } public double getWeight() { return weight; } // Regular method โ shared by all animals public void displayInfo() { System.out.println("๐ฆฎ Name: " + name + " | Age: " + age + "yrs | Weight: " + weight + "kg"); } // Abstract methods โ each subclass defines these! public abstract void makeSound(); public abstract void feed(); } // ============================================ // SUBCLASSES // ============================================ class Lion extends Animal implements Trainable { public Lion(String n, int a, double w) { super(n, a, w); } @Override public void makeSound() { System.out.println(getName() + ": ROAARRR! ๐ฆ"); } @Override public void feed() { System.out.println(getName() + " gets 10kg of fresh meat. ๐ฅฉ"); } @Override public void performTrick(String trick) { System.out.println(getName() + " performs: " + trick + " ๐ช"); } } class Penguin extends Animal implements Swimmable, Trainable { public Penguin(String n, int a, double w) { super(n, a, w); } @Override public void makeSound() { System.out.println(getName() + ": Squawk squawk! ๐ง"); } @Override public void feed() { System.out.println(getName() + " gets a bucket of fish! ๐"); } @Override public void swim() { System.out.println(getName() + " dives and swims gracefully! ๐"); } @Override public void performTrick(String trick) { System.out.println(getName() + " waddles and does: " + trick); } } class Eagle extends Animal implements Flyable { public Eagle(String n, int a, double w) { super(n, a, w); } @Override public void makeSound() { System.out.println(getName() + ": Screech! ๐ฆ "); } @Override public void feed() { System.out.println(getName() + " catches a fish from the pond! ๐ "); } @Override public void fly() { System.out.println(getName() + " soars high above the clouds! โ๏ธ"); } } // ============================================ // MAIN โ the Zoo opens! // ============================================ public class Zoo { public static void main(String[] args) { // Create our animals using constructors Animal[] animals = { new Lion("Simba", 5, 190.0), new Penguin("Pingu", 3, 5.0), new Eagle("Baldy", 7, 6.5) }; System.out.println("=== ๐ฆ Welcome to OOP Zoo! ๐ฆ ==="); // Polymorphism โ one loop, each animal acts differently! for (Animal a : animals) { a.displayInfo(); a.makeSound(); a.feed(); System.out.println("---"); } // Use interfaces specifically System.out.println("\n=== ๐ช Special Shows ==="); Penguin p = (Penguin) animals[1]; p.swim(); p.performTrick("slide on ice"); Eagle e = (Eagle) animals[2]; e.fly(); } }
Now that you know OOP, here are awesome projects to try:
- ๐ฎ A text-based RPG game with Warriors, Mages, and Rogues
- ๐ฆ A bank system with Checking and Savings accounts
- ๐ A simple shopping cart with Products and Discounts
- ๐ซ A school management system with Students and Teachers
- ๐ A space exploration game with Planets and Spaceships