Object-oriented programming (OOP) is a programming paradigm that uses objects to create applications.

In addition, it offers us several advantages, including:

  • Allowing code reuse and extension.
  • Facilitating teamwork.
  • Speeding up software development.
  • Programming that resembles the real world, based on "objects".

It is based on three main parts:

  • Encapsulation: Private variables with methods that allow us to use the variables.
  • Inheritance: We can make a class inherit attributes and methods from another class.
  • Polymorphism: Functions, methods, variables, or objects that can have several different forms.

Below, we will look at different examples for each of them.

Encapsulation

In encapsulation, we use private variables and allow access to them through methods that let us initialize the variables. These methods are known as getters and setters. This way, we can control that only the object's internal methods can access them and prevent other objects from changing an object's internal state unexpectedly.

The structure would be as follows:

class Encapsulacion{    
    private int value;
    public int getValue(){
        return value;  
    }

    public void setValue(int value){
        this.value = value;  
    }
}

Inheritance

Through inheritance, we can make a class inherit variables and methods from another class.

The class we inherit from is called a superclass or parent class. A subclass has its own attributes and methods added to the attributes and methods of the superclass. To create inheritance, the reserved word extends is used.

For example, all vehicles need to start. So we can define a class that defines the start method for any vehicle, and then define more specific vehicles with their characteristics and their way of starting.

abstract class Vehiculo{
    abstract public void start();
}

An abstract class allows us to define the structure without the implementation. Then we can define our classes that inherit:

class Coche extends Vehiculo {    
    Coche(){}        
    @Override public void start(){
        System.out.println("Soy un coche");    
    }
}

Polymorphism

Polymorphism is the ability of a function, method, variable, or object to possess several different forms. To simplify it, we could say that the same identifier shares several different meanings.

In general, we speak of:

  • Assignment polymorphism
  • Pure polymorphism
  • Overloading
  • Inclusion polymorphism

Assignment polymorphism

The same referenced variable can refer to more than one type of Class. In this way, we can group objects of different classes that share a superclass.

For example, we don't care if it's a car or a motorcycle; we want to start the vehicle. We could have the following code:

Vehicle class:

abstract class Vehiculo{
    abstract public void start();
}

Car class:

abstract class Vehiculo{
    abstract public void start();
}

Main program:

Coche car = new Coche();        
car.start();        
Vehiculo car2 = new Coche();        
car2.start();

Program output:

Soy un coche 
Soy un coche

Pure polymorphism

It is used to name a function or method that can receive several types of arguments at runtime. We can accept multiple objects of different types at runtime. For example, a method that accepts any type of vehicle:

class PolimorfismoPuro{    
    public void funcion(Vehículo v){
        // Se ejecutará para cualquier tipo de vehículo, sea coche, camión, moto…    
    }
}

Overloading

Overloading occurs when two or more functions share the same identifier, but have a different argument list. For example, a function defined in a class that accepts characters and integers:

class Sobrecarga{    
    public void funcion(int a){
 
    }

    public void funcion(char a){
 
    }
}

Inclusion polymorphism

A subclass defines a method that exists in a superclass with an argument list.

For example, we can have chess pieces. All pieces can move, but that method will be defined by the specific piece. We can override this method for a piece using the reserved word @Override.

We can have the piece defined in an abstract way:

abstract class Pieza { 
    public abstract void movimiento(byte X, byte Y); 
} 

And a specific piece, for example the knight, with its movement defined.

class Caballo extends Pieza { 
    @Override public void movimiento(byte X, byte Y) { ... } 
}