Java Object-Oriented Programming (OOP)

1. What is Object-Oriented Programming?

Object-Oriented Programming is a programming paradigm that organizes code into objects, which are instances of classes containing both data and code. It’s like creating a blueprint (class) for a house and then building actual houses (objects) from that blueprint.

2. Four Main Principles of OOP

2.1 Encapsulation

Encapsulation is like putting related data and methods that operate on that data within a protective wrapper (class).

public class BankAccount {
    // Private variables (data hiding)
    private double balance;
    private String accountNumber;

    // Public methods to access private data (getters and setters)
    public double getBalance() {
        return balance;
    }

    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }
}

2.2 Inheritance

Inheritance allows a class to inherit attributes and methods from another class, creating a parent-child relationship.

// Parent class
public class Animal {
    protected String name;

    public void eat() {
        System.out.println(name + " is eating");
    }
}

// Child class inheriting from Animal
public class Dog extends Animal {
    public Dog(String name) {
        this.name = name;
    }

    public void bark() {
        System.out.println(name + " is barking");
    }
}

// Usage
Dog myDog = new Dog("Buddy");
myDog.eat();  // Inherited method
myDog.bark(); // Dog-specific method

2.3 Polymorphism

Polymorphism allows objects to take multiple forms. There are two types:

Method Overriding (Runtime Polymorphism)

public class Animal {
    public void makeSound() {
        System.out.println("Some sound");
    }
}

public class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Meow");
    }
}

public class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Woof");
    }
}

// Usage
Animal animal1 = new Cat();
Animal animal2 = new Dog();
animal1.makeSound(); // Outputs: Meow
animal2.makeSound(); // Outputs: Woof

Method Overloading (Compile-time Polymorphism)

public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }

    public double add(double a, double b) {
        return a + b;
    }

    public int add(int a, int b, int c) {
        return a + b + c;
    }
}

2.4 Abstraction

Abstraction helps hide complex implementation details and show only necessary features.

// Abstract class
abstract class Vehicle {
    abstract void startEngine();

    // Concrete method
    public void stop() {
        System.out.println("Vehicle stopped");
    }
}

// Interface
interface Flyable {
    void fly();
    void land();
}

// Concrete class implementing abstract class and interface
public class Airplane extends Vehicle implements Flyable {
    @Override
    void startEngine() {
        System.out.println("Airplane engine starting");
    }

    @Override
    public void fly() {
        System.out.println("Airplane is flying");
    }

    @Override
    public void land() {
        System.out.println("Airplane is landing");
    }
}

3. Classes and Objects

3.1 Class Structure

public class Student {
    // Instance variables (attributes)
    private String name;
    private int age;

    // Constructor
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Methods
    public void study() {
        System.out.println(name + " is studying");
    }

    // Getters and Setters
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

3.2 Creating Objects

Student student1 = new Student("John", 20);
Student student2 = new Student("Mary", 21);

student1.study();
System.out.println(student2.getName());

4. Advanced OOP Concepts

4.1 Static Members

public class Counter {
    private static int count = 0;  // Static variable

    public Counter() {
        count++;
    }

    public static int getCount() {  // Static method
        return count;
    }
}

4.2 Final Keyword

// Final class (cannot be inherited)
final class Constants {
    // Final variable (cannot be changed)
    final static double PI = 3.14159;

    // Final method (cannot be overridden)
    final void display() {
        System.out.println("This cannot be overridden");
    }
}

4.3 Interface Implementation with Default Methods

interface Drawable {
    void draw();  // Abstract method

    // Default method
    default void resize() {
        System.out.println("Resizing...");
    }
}

class Circle implements Drawable {
    @Override
    public void draw() {
        System.out.println("Drawing Circle");
    }
}

5. Best Practices

  1. Follow Naming Conventions
  • Classes: PascalCase (Employee, BankAccount)
  • Methods/Variables: camelCase (getName, firstName)
  1. Encapsulation Guidelines
  • Make instance variables private
  • Provide public getters/setters when needed
  • Validate data in setters
  1. Inheritance Tips
  • Use inheritance only for “is-a” relationships
  • Prefer composition over inheritance when possible
  • Keep inheritance hierarchies shallow
  1. General Tips
  • One class per file
  • Keep classes focused and single-responsibility
  • Use meaningful names for classes, methods, and variables
  • Document your code with comments

6. Practical Example: Complete Program

public class LibrarySystem {
    public static void main(String[] args) {
        // Creating books
        Book book1 = new Book("Java Programming", "John Doe");
        Book book2 = new Book("OOP Concepts", "Jane Smith");

        // Creating library members
        LibraryMember member1 = new Student("Alice", 101);
        LibraryMember member2 = new Teacher("Bob", 201);

        // Demonstrating polymorphism
        member1.borrowBook(book1);
        member2.borrowBook(book2);
    }
}

abstract class LibraryMember {
    protected String name;
    protected int id;

    public LibraryMember(String name, int id) {
        this.name = name;
        this.id = id;
    }

    abstract void borrowBook(Book book);
}

class Student extends LibraryMember {
    public Student(String name, int id) {
        super(name, id);
    }

    @Override
    void borrowBook(Book book) {
        System.out.println("Student " + name + " borrowed " + book.getTitle());
    }
}

class Teacher extends LibraryMember {
    public Teacher(String name, int id) {
        super(name, id);
    }

    @Override
    void borrowBook(Book book) {
        System.out.println("Teacher " + name + " borrowed " + book.getTitle());
    }
}

class Book {
    private String title;
    private String author;

    public Book(String title, String author) {
        this.title = title;
        this.author = author;
    }

    public String getTitle() {
        return title;
    }
}

This guide provides a solid foundation in Java OOP concepts. Each concept is explained with practical examples that you can try and modify. Understanding these concepts is crucial for becoming a proficient Java developer.

Leave a Reply

Your email address will not be published. Required fields are marked *