What are OOPS Concepts in Java?
Introduction
Object-Oriented Programming (OOP) is a programming paradigm that is based on the concept of objects, which can contain data and code to manipulate that data. Java is a fully object-oriented programming language, and as such, it provides several key concepts that make up the foundation of OOP. In this tutorial, we will explore the main OOP concepts in Java, along with examples and code. It is based on the principles of:
- Encapsulation
- Inheritance
- Polymorphism
- Abstraction
Advantages of using OOPs:
Modularity: OOPs allows breaking down the code into smaller, more manageable pieces known as objects. This makes the code more modular, easier to understand, and maintain.
Reusability: OOPs allow reusing the code by creating new objects from existing ones. This saves time and effort and reduces the likelihood of errors.
Encapsulation: OOPs encapsulates data and behavior in objects, which are hidden from the outside world. This provides data security and allows the objects to be used independently of each other.
Inheritance: OOPs allows the creation of new classes by inheriting properties and methods from existing ones. This promotes code reuse and saves time and effort.
Polymorphism: OOPs allows creating objects of different types and using them interchangeably. This makes the code more flexible and adaptable to changing requirements.
Abstraction: OOPs allows hiding the complexity of the code by creating abstract classes and interfaces. This makes the code more modular, easier to understand, and maintain.
- Class and Object
The class is a blueprint or a template for creating objects. It defines the properties and behaviors of an object. An object is an instance of a class that has its own state and behavior. In Java, we create a class using the class
keyword. Here is an example of a Person
class:
javapublic class Person {
// Properties
String name;
int age;
String address;
// Behaviors
public void walk() {
System.out.println(name + " is walking.");
}
public void talk(String message) {
System.out.println(name + " says: " + message);
}
}
In the above code, we have defined a Person
class with three properties: name
, age
, and address
. We have also defined two behaviors: walk()
and talk()
, which represent actions that a person can perform.
To create an object of this class, we use the new
keyword, followed by the name of the class and any arguments needed to initialize the object. Here is an example:
javaPerson john = new Person();
john.name = "John";
john.age = 25;
john.address = "123 Main Street";
john.walk(); // Output: John is walking.
john.talk("Hello, how are you?"); // Output: John says: Hello, how are you?
In the above code, we have created an object of the Person
class called john
, and initialized its properties using dot notation. We have also called the walk()
and talk()
methods on the john
object.
- Encapsulation
Encapsulation is the practice of hiding data and behavior within a class, and only exposing a public interface to the outside world. This helps to ensure that the data is protected from unwanted modification and that the behavior is consistent and predictable. In Java, we can use access modifiers to control the visibility of properties and methods within a class.
There are four access modifiers in Java:
public
private
protected
- default (no modifier)
javapublic class Person {
// Private properties
private String name;
private int age;
private String address;
// Public methods to access and modify the private properties
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
// Behaviors
public void walk() {
System.out.println(name + " is walking.");
}
public void talk(String message) {
System.out.println(name + " says: " + message);
}
}
In the above code, we have made the name
, age
, and address
properties private, and provided public methods to access and modify these properties. This ensures that the data is protected from unwanted modification and that any changes to the data are made using a consistent and controlled interface.
- Inheritance
Inheritance is the practice of creating a new class from an existing class and inheriting its properties and behaviors. The new class is called the subclass or derived class, and the existing class is called the superclass or base class. In Java, we use the extends
keyword to create a subclass of a superclass. Here is an example of inheritance:
javapublic class Employee extends Person {
// Additional properties
String department;
double salary;
// Additional behavior
public void work() {
System.out.println(name + " is working in the " + department + " department.");
}
}
In the above code, we have created a Employee
class that extends the Person
class. This means that the Employee
class inherits all the properties and behaviors of the Person
class, and can add its own properties and behaviors. In this case, we have added the department
and salary
properties, and the work()
behavior.
To create an object of the Employee
class, we can use the same syntax as before:
javaEmployee jane = new Employee();
jane.setName("Jane");
jane.setAge(30);
jane.setAddress("456 Oak Street");
jane.department = "Marketing";
jane.salary = 50000;
jane.walk(); // Output: Jane is walking.
jane.talk("Hi there."); // Output: Jane says: Hi there.
jane.work(); // Output: Jane is working in the Marketing department.
In the above code, we have created an object of the Employee
class called jane
, and initialized its properties using the setName()
, setAge()
, and setAddress()
methods inherited from the Person
class, as well as the department
and salary
properties specific to the Employee
class.
- Polymorphism
Polymorphism is the practice of using a single interface to represent multiple types of objects. In Java, polymorphism is achieved through:
- Method Overriding
- Method Overloading
4.1. Method overriding occurs when a subclass provides a specific implementation of a method that is already defined in its superclass. Here is an example:
javapublic class Animal {
public void makeSound() {
System.out.println("The animal makes a sound.");
}
}
public class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("The cat meows.");
}
}
public class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("The dog barks.");
}
}
In the above code, we have created an Animal
class with a makeSound()
method that prints a generic message. We have also created Cat
and Dog
classes that extend the Animal
class and override the makeSound()
method with their own specific implementations. This allows us to treat Cat
and Dog
objects as Animal
objects, while still retaining their specific behaviors.
javaAnimal animal1 = new Animal();
Animal animal2 = new Cat();
Animal animal3 = new Dog();
animal1.makeSound(); // Output: The animal makes a sound.
animal2.makeSound(); // Output: The cat meows.
animal3.makeSound(); // Output: The dog barks.
In the above code, we have created three objects of different types (Animal
, Cat
, and Dog
), and called the makeSound()
method on each of them. Because the makeSound()
method is overridden in the Cat
and Dog
classes, the specific implementation for each subclass is called.
4.2. Method overloading occurs when a class has multiple methods with the same name, but different parameters. Here is an example:
javapublic class Calculator {
public int add(int x, int y) {
return x + y;
}
public double add(double x, double y) {
return x + y;
}
public int add(int x, int y, int z) {
return x + y + z;
}
}
public class Main {
public static void main(String[] args) {
Calculator calculator = new Calculator();
System.out.println(calculator.add(2, 3)); // Output: 5
System.out.println(calculator.add(2.5, 3.5)); // Output: 6.0
System.out.println(calculator.add(2, 3, 4)); // Output: 9
}
}
In the above code, we have created a Calculator
class with three add()
methods. Each method has the same name, but a different number and type of parameters. This allows us to use the same method name for multiple related behaviors, making the code easier to read and maintain.
- Abstraction
Abstraction is the practice of hiding implementation details while showing only the necessary information to the user. In Java, abstraction is achieved through:
- Abstract Classes
- Interfaces.
5.1. Abstract classes are classes that cannot be instantiated but can be extended by other classes. Abstract classes can contain abstract methods, which are declared but not implemented in the abstract class and must be implemented by any concrete subclass. Here is an example:
javapublic abstract class Shape {
// Abstract method
public abstract double area();
// Concrete method
public void print() {
System.out.println("This is a shape.");
}
}
public class Rectangle extends Shape {
// Properties
double length;
double width;
// Constructor
public Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
// Implementation of abstract method
@Override
public double area() {
return length * width;
}
}
public class Main {
public static void main(String[] args) {
Shape shape = new Rectangle(5, 10);
shape.print(); // Output: This is a shape.
System.out.println("Area: " + shape.area()); // Output: Area: 50.0
}
}
In the above code, we have created an abstract
Shape
class with an abstract area()
method and a concrete print()
method. We have also created a Rectangle
class that extends the Shape
class and implements the area()
method. We can create an object of the Rectangle
class and assign it to a Shape
variable, which allows us to call the print()
and area()
methods on the object without knowing the specific implementation details of the Rectangle
class.
5.2. Interfaces are similar to abstract classes, but can contain only abstract methods and constants. Interfaces are implemented by classes using the implements
keyword, and a class can implement multiple interfaces. Here is an example:
javapublic interface Animal {
void move();
}
public abstract class Mammal {
protected int age;
public abstract void speak();
public void breathe() {
System.out.println("Inhale, exhale");
}
}
public class Dog extends Mammal implements Animal {
@Override
public void move() {
System.out.println("Running on four legs");
}
@Override
public void speak() {
System.out.println("Bark!");
}
}
In this example, we have an Animal
interface with an abstract move()
method, and an abstract
Mammal
class with an abstract speak()
method and a non-abstract breathe()
method. The Dog
class extends the Mammal
class and implements the Animal
interface, providing its own implementation of the move()
and speak()
methods.
Note that the Mammal
class has an age
instance variable, while the Animal
interface has none. Also, the Mammal
class has a non-abstract breathe()
method with a default implementation, while the Animal
interface has no non-abstract methods. Finally, the Dog
class extends the Mammal
class and implements the Animal
interface, showing how a class can inherit from an abstract class and implement an interface at the same time.
Overall, both abstract classes and interfaces are useful tools for defining common behaviors and promoting code reuse in Java, but they have different strengths and limitations depending on the specific use case.
Comments
Post a Comment