Programación Orientada a Objetos en Java: Conceptos Clave
-
Yamil Villarreal
- 06 Jul, 2024

Cuando empecé a aprender Java, confieso que me abrumaban todos esos términos nuevos: clases, objetos, herencia, polimorfismo, encapsulamiento, abstracción… ¡era como aprender un idioma desde cero! Si te pasa algo parecido, tranquilo, a todos nos pasa. Lo importante es irlos entendiendo poco a poco y ver cómo todo cobra sentido con la práctica. Aquí te dejo una guía sencilla y cercana para que esos conceptos de la POO en Java te resulten más claros (y útiles).
Clases y Objetos
Clases
Una clase es como un plano, el molde para crear objetos. Imagina que tienes la receta de tu comida favorita: los
ingredientes y los pasos son la clase, ¡y el platillo listo es el objeto!
Si eres más visual, piensa en el plano de un vehículo. Esa clase tendrá atributos como marca, modelo y color, y métodos
como encender, frenar y acelerar.
public class Vehiculo {
// Atributos de la clase
String marca;
String modelo;
String color;
// Métodos de la clase
void encendido() {
System.out.println("El vehiculo está encendido.");
}
void frenar() {
System.out.println("El vehiculo está frenando.");
}
void acelerar() {
System.out.println("El vehiculo está acelerando.");
}
}
Objetos
El objeto es la “instancia” de la clase, es decir, lo que realmente usas en el programa. Si la clase es el plano, el objeto es el vehículo que construyes a partir de ese plano.
public class Main {
public static void main(String[] args) {
Vehiculo miVehiculo = new Vehiculo();
miVehiculo.marca = "Toyota";
miVehiculo.modelo = "Yaris Cross";
miVehiculo.color = "Rojo";
// Usar los métodos del objeto
miVehiculo.encendido();
miVehiculo.acelerar();
miVehiculo.frenar();
}
}
Herencia
Aquí me gusta usar la analogía de los autos “tuneados” (mi hermana es fan): a partir de un vehículo base, puedes agregarle nuevas características sin tener que crear todo desde cero. En Java, la herencia permite crear nuevas clases que reutilizan y amplían el comportamiento de otras. Así evitas duplicar código y haces tu vida más sencilla.
// Clase base o superclase
public class Animal {
void comer() {
System.out.println("El animal está comiendo.");
}
}
// Clase derivada o subclase
public class Perro extends Animal {
void ladrar() {
System.out.println("El perro está ladrando. Guau!");
}
}
public class Main {
public static void main(String[] args) {
Perro miPerro = new Perro();
miPerro.comer(); // Heredado de Animal
miPerro.ladrar(); // Propio de Perro
}
}
Polimorfismo
El polimorfismo suena complicado, pero en realidad es simplemente la capacidad de tratar objetos de diferentes clases de la misma manera, usando una clase base común.
Sobrecarga
Permite definir varios métodos con el mismo nombre, pero diferentes parámetros. Así puedes “personalizar” una acción según lo que necesites.
public class Vehiculo {
public void mover(String direccion) {
System.out.println("El vehículo se mueve hacia " + direccion);
}
public void mover(int velocidad) {
System.out.println("El vehículo se mueve a " + velocidad + " km/h");
}
public void mover(int x, int y) {
System.out.println("El vehículo se mueve en las coordenadas (" + x + ", " + y + ")");
}
}
Anulación (Override)
Permite que una subclase cambie el comportamiento de un método heredado de la superclase.
// Clase base
public class Vehiculo {
public void mover() {
System.out.println("El vehículo se está moviendo");
}
}
// Subclase Auto
public class Auto extends Vehiculo {
@Override
public void mover() {
System.out.println("El auto está conduciendo en la carretera");
}
}
// Subclase Bicicleta
public class Bicicleta extends Vehiculo {
@Override
public void mover() {
System.out.println("La bicicleta está pedaleando");
}
}
Encapsulamiento
Piensa en el encapsulamiento como los controles de tu vehículo: puedes acelerar, frenar, o ver el nivel de combustible, pero no puedes modificar directamente cómo funciona el motor interno. En Java, esto se logra usando atributos privados y métodos públicos para accederlos.
public class Vehiculo {
private int velocidad;
private int nivelCombustible;
public Vehiculo(int velocidadInicial, int nivelCombustibleInicial) {
this.velocidad = velocidadInicial;
this.nivelCombustible = nivelCombustibleInicial;
}
public int getVelocidad() {
return velocidad;
}
public void setVelocidad(int nuevaVelocidad) {
if (nuevaVelocidad >= 0) {
this.velocidad = nuevaVelocidad;
} else {
System.out.println("La velocidad no puede ser negativa");
}
}
public int getNivelCombustible() {
return nivelCombustible;
}
public void setNivelCombustible(int nuevoNivelCombustible) {
if (nuevoNivelCombustible >= 0 && nuevoNivelCombustible <= 100) {
this.nivelCombustible = nuevoNivelCombustible;
} else {
System.out.println("El nivel de combustible debe estar entre 0 y 100");
}
}
public void mostrarEstado() {
System.out.println("Velocidad: " + velocidad + " km/h");
System.out.println("Nivel de combustible: " + nivelCombustible + "%");
}
}
Abstracción
La abstracción es como mirar el tablero del carro: ves solo lo esencial (velocidad, combustible), pero no te preocupas por el detalle del motor. En Java, esto se logra usando clases abstractas e interfaces.
Clases Abstractas
Una clase abstracta es un modelo genérico, no puedes crear objetos de ella, pero sí de sus subclases. Sirve para definir lo que “debe” hacer una familia de clases, pero no cómo lo hacen.
// Clase abstracta Vehiculo
public abstract class Vehiculo {
public abstract void moverse();
public void mostrarEstado() {
System.out.println("El vehículo está listo para moverse");
}
}
public class Auto extends Vehiculo {
@Override
public void moverse() {
System.out.println("El auto está conduciendo en la carretera");
}
}
public class Bicicleta extends Vehiculo {
@Override
public void moverse() {
System.out.println("La bicicleta está pedaleando cuesta arriba");
}
}
Interfaces
Una interfaz define “qué” debe hacer una clase, pero no “cómo”. Es como un contrato: si lo implementas, debes cumplir con todos los métodos definidos.
public interface Vehiculo {
void moverse();
void detenerse();
}
public class Auto implements Vehiculo {
@Override
public void moverse() {
System.out.println("El auto está conduciendo en la carretera");
}
@Override
public void detenerse() {
System.out.println("El auto se ha detenido");
}
}
public class Bicicleta implements Vehiculo {
@Override
public void moverse() {
System.out.println("La bicicleta está pedaleando en el carril izquierdo");
}
@Override
public void detenerse() {
System.out.println("La bicicleta se ha detenido");
}
}
Conclusión
Todos estos conceptos suenan complejos al principio, pero son las piezas básicas para programar bien en Java (¡y en muchos otros lenguajes!). Con la práctica, verás cómo puedes construir sistemas más robustos, fáciles de mantener y hasta divertidos de crear.