Object-Oriented Programming in Java
Welcome to the second part of the Learn Java series! In this section, we will dive into one of Java's core concepts: Object-Oriented Programming (OOP). OOP allows us to create programs that are more modular, reusable, and easier to maintain. Java is a fully object-oriented language, which makes OOP essential to mastering the language.
What is Object-Oriented Programming?
OOP is a programming paradigm based on the concept of "objects," which can contain data and code that manipulates the data. The four core principles of OOP are:
- Encapsulation - Wrapping data (fields) and code (methods) together into a single unit, or class. Access to the data is restricted through well-defined interfaces (getters/setters).
- Inheritance - A class can inherit fields and methods from another class, allowing for code reuse and the creation of hierarchical relationships.
- Polymorphism - The ability of different objects to respond to the same method call in different ways, typically achieved through method overriding or interfaces.
- Abstraction - Hiding the complex implementation details of an object and exposing only the necessary functionalities to the outside world.
Classes and Objects
In Java, a class is a blueprint for creating objects (instances). Each object has fields (attributes) and methods (behavior). Let’s look at an example:
public class Car {
// Fields (attributes)
String model;
String color;
int year;
// Constructor
public Car(String model, String color, int year) {
this.model = model;
this.color = color;
this.year = year;
}
// Method (behavior)
public void start() {
System.out.println(model + " is starting.");
}
}
In this example:
Car
is a class with three fields:model
,color
, andyear
.- The constructor
Car(String, String, int)
initializes the object’s fields when an object is created. - The
start
method defines the behavior of the car, which prints a message when the car starts.
Creating an Object
To create an object from the Car
class, you would do the following:
public class Main {
public static void main(String[] args) {
// Creating an object of the Car class
Car myCar = new Car("Tesla", "Red", 2023);
myCar.start(); // Output: Tesla is starting.
}
}
This code creates an instance of the Car
class named myCar
and calls its start
method.
Inheritance
Inheritance allows one class (subclass) to inherit fields and methods from another class (superclass). Let’s modify our example:
public class ElectricCar extends Car {
int batteryLife;
public ElectricCar(String model, String color, int year, int batteryLife) {
super(model, color, year);
this.batteryLife = batteryLife;
}
public void charge() {
System.out.println(model + " is charging. Battery life: " + batteryLife + " hours.");
}
}
In this example:
ElectricCar
is a subclass ofCar
, meaning it inherits the fields and methods ofCar
.- The
super()
call in the constructor passes values to theCar
class constructor. ElectricCar
adds a new fieldbatteryLife
and a new methodcharge()
in addition to the inherited ones.
Polymorphism
Polymorphism allows us to use a subclass object wherever a superclass object is expected. For example:
public class Main {
public static void main(String[] args) {
Car myCar = new ElectricCar("Tesla", "Red", 2023, 12);
myCar.start(); // Output: Tesla is starting.
// myCar.charge(); // This would cause a compilation error because myCar is of type Car, not ElectricCar
}
}
Here, myCar
is a reference of type Car
, but it points to an ElectricCar
object. The method start()
is called based on the object type (ElectricCar), but charge()
cannot be called directly since it belongs to the subclass.
Encapsulation
Encapsulation is the practice of keeping fields private and providing public methods to access and modify them. This protects the internal state of an object from unintended modification. For example:
public class Car {
private String model;
private String color;
private int year;
public Car(String model, String color, int year) {
this.model = model;
this.color = color;
this.year = year;
}
// Getter and Setter methods
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
}
Here, the fields model
, color
, and year
are private, meaning they can only be accessed through public getter and setter methods.
Abstraction
Abstraction is used to hide the internal implementation details of an object and only expose what is necessary. In Java, abstraction can be achieved using abstract classes and interfaces.
Abstract Classes
An abstract class is a class that cannot be instantiated on its own and is meant to be subclassed. It can have abstract methods (without implementation) that must be implemented by subclasses. Here’s an example:
abstract class Animal {
abstract void makeSound();
public void eat() {
System.out.println("This animal eats food.");
}
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Woof! Woof!");
}
}
In this example:
Animal
is an abstract class with an abstract methodmakeSound()
and a concrete methodeat()
.Dog
is a subclass ofAnimal
and provides an implementation for themakeSound()
method.
Interfaces
Interfaces in Java are abstract types that can contain method signatures but no implementation. A class can implement multiple interfaces, providing implementations for all of their methods. Here’s an example:
interface Drivable {
void drive();
}
class Car implements Drivable {
@Override
public void drive() {
System.out.println("The car is driving.");
}
}
In this example:
Drivable
is an interface with a single methoddrive()
.Car
implements theDrivable
interface and provides an implementation for thedrive()
method.
Conclusion
Object-Oriented Programming (OOP) is a powerful paradigm that helps you build robust and maintainable software. By understanding the principles of OOP, you can create classes and objects that model real-world entities and interactions more effectively. In this lesson, we covered the core principles of OOP, including encapsulation, inheritance, polymorphism, and abstraction, along with examples to illustrate these concepts.