Introducción a POO
La Programación Orientada a Objetos (POO) es un paradigma de programación que organiza el código en "objetos" que combinan datos y comportamientos relacionados. En Java, todo es un objeto (excepto los tipos primitivos).
Clase
Plantilla o molde que define las propiedades y comportamientos de un objeto. Es como un plano de construcción.
Objeto
Instancia concreta de una clase. Es la "cosa real" creada a partir del molde.
Clases y Objetos
Simulador de Clases y Objetos
// Crear un objeto (instancia) de la clase Coche
Coche miCoche = new Coche("Toyota", "Corolla", 2023);
// Usar métodos del objeto
miCoche.acelerar(50);
miCoche.mostrarInfo();
Constructores
public class Estudiante {
private String nombre;
private int edad;
private String carrera;
// 1. Constructor por defecto (sin parámetros)
public Estudiante() {
this.nombre = "Sin nombre";
this.edad = 18;
this.carrera = "No asignada";
}
// 2. Constructor con parámetros
public Estudiante(String nombre, int edad, String carrera) {
this.nombre = nombre;
this.edad = edad;
this.carrera = carrera;
}
// 3. Constructor de copia
public Estudiante(Estudiante otro) {
this.nombre = otro.nombre;
this.edad = otro.edad;
this.carrera = otro.carrera;
}
// 4. Constructor con algunos parámetros (sobrecarga)
public Estudiante(String nombre, int edad) {
this(nombre, edad, "Ingeniería"); // Llama a otro constructor
}
}
Demostración Interactiva
Modificadores de Acceso
Público
Accesible desde cualquier clase en cualquier paquete
public class MiClase {
public int valor; // Accesible desde cualquier parte
}
Privado
Solo accesible dentro de la misma clase
public class MiClase {
private int secreto; // Solo esta clase puede acceder
}
Protegido
Accesible en la misma clase, paquete y subclases
public class MiClase {
protected int familiar; // Clase, paquete y herederas
}
Por Defecto
Accesible solo en el mismo paquete (sin modificador)
public class MiClase {
int paquete; // Solo clases en el mismo paquete
}
| Modificador | Misma Clase | Mismo Paquete | Subclase | Cualquier Lugar |
|---|---|---|---|---|
private |
✓ | ✗ | ✗ | ✗ |
(default) |
✓ | ✓ | ✗ | ✗ |
protected |
✓ | ✓ | ✓ | ✗ |
public |
✓ | ✓ | ✓ | ✓ |
Encapsulamiento
Getters y Setters: Protegiendo los Datos
El encapsulamiento oculta los detalles internos de una clase y solo expone una interfaz controlada mediante métodos públicos (getters y setters).
public class CuentaBancaria {
// Atributos PRIVADOS (encapsulados)
private String titular;
private double saldo;
private String numeroCuenta;
// Constructor
public CuentaBancaria(String titular, double saldoInicial) {
this.titular = titular;
this.saldo = saldoInicial;
this.numeroCuenta = generarNumeroCuenta();
}
// GETTERS (métodos para leer)
public String getTitular() {
return titular;
}
public double getSaldo() {
return saldo;
}
public String getNumeroCuenta() {
return numeroCuenta;
}
// SETTERS con validación (métodos para modificar)
public void setTitular(String titular) {
if (titular != null && !titular.trim().isEmpty()) {
this.titular = titular;
}
}
public void depositar(double cantidad) {
if (cantidad > 0) {
saldo += cantidad;
}
}
public boolean retirar(double cantidad) {
if (cantidad > 0 && cantidad <= saldo) {
saldo -= cantidad;
return true;
}
return false;
}
private String generarNumeroCuenta() {
// Método privado, solo usado internamente
return "ES" + (int)(Math.random() * 1000000000);
}
}
Herencia
Árbol de Herencia: Sistema de Personas
La herencia permite crear nuevas clases basadas en clases existentes, reutilizando y extendiendo su funcionalidad.
Persona
Estudiante
Profesor
// CLASE BASE
public class Persona {
protected String nombre;
protected int edad;
public void presentarse() {
System.out.println("Hola, soy " + nombre);
}
}
// HERENCIA: Estudiante ES UNA Persona
public class Estudiante extends Persona {
private String matricula;
// Sobrescritura de método
@Override
public void presentarse() {
super.presentarse(); // Llama al método de la clase base
System.out.println("Soy estudiante con matrícula: " + matricula);
}
public void estudiar() {
System.out.println(nombre + " está estudiando...");
}
}
// HERENCIA: Profesor ES UNA Persona
public class Profesor extends Persona {
private String especialidad;
@Override
public void presentarse() {
System.out.println("Soy el profesor " + nombre +
", especialista en " + especialidad);
}
public void enseñar() {
System.out.println(nombre + " está enseñando " + especialidad);
}
}
Polimorfismo
Un Nombre, Múltiples Formas
El polimorfismo permite que objetos de diferentes clases sean tratados como objetos de una clase común.
Rectángulo
Clase que calcula área y perímetro
Círculo
Clase que calcula área y perímetro
Triángulo
Clase que calcula área y perímetro
// INTERFAZ COMÚN
public interface Figura {
double calcularArea();
double calcularPerimetro();
}
// CLASES QUE IMPLEMENTAN LA INTERFAZ
public class Rectangulo implements Figura {
private double base, altura;
@Override
public double calcularArea() {
return base * altura;
}
@Override
public double calcularPerimetro() {
return 2 * (base + altura);
}
}
public class Circulo implements Figura {
private double radio;
@Override
public double calcularArea() {
return Math.PI * radio * radio;
}
@Override
public double calcularPerimetro() {
return 2 * Math.PI * radio;
}
}
// USO POLIMÓRFICO
Figura[] figuras = new Figura[3];
figuras[0] = new Rectangulo();
figuras[1] = new Circulo();
figuras[2] = new Triangulo();
// Mismo método, diferentes comportamientos
for (Figura figura : figuras) {
System.out.println("Área: " + figura.calcularArea());
System.out.println("Perímetro: " + figura.calcularPerimetro());
}
Clases Abstractas e Interfaces
Comparación: Abstractas vs Interfaces
// EJEMPLO DE CLASE ABSTRACTA
public abstract class Animal {
// Atributos
protected String nombre;
protected int edad;
// Constructor
public Animal(String nombre, int edad) {
this.nombre = nombre;
this.edad = edad;
}
// Método abstracto (DEBE ser implementado)
public abstract void hacerSonido();
// Método concreto (YA está implementado)
public void dormir() {
System.out.println(nombre + " está durmiendo...");
}
// Método final (NO puede ser sobrescrito)
public final void respirar() {
System.out.println(nombre + " está respirando");
}
}
// EJEMPLO DE INTERFACE
public interface Volador {
// Constante (implícitamente public static final)
int ALTURA_MAXIMA = 10000;
// Método abstracto (implícitamente public abstract)
void volar();
// Método default (Java 8+)
default void aterrizar() {
System.out.println("Aterrizando...");
}
// Método static (Java 8+)
static void mostrarInfo() {
System.out.println("Interface para objetos que vuelan");
}
// Método private (Java 9+)
private void logVuelo() {
System.out.println("Registrando vuelo...");
}
}
// CLASE QUE USA AMBOS
public class Pajaro extends Animal implements Volador {
public Pajaro(String nombre, int edad) {
super(nombre, edad);
}
@Override
public void hacerSonido() {
System.out.println("¡Pío pío!");
}
@Override
public void volar() {
System.out.println(nombre + " está volando a gran altura");
}
}
| Característica | Clase Abstracta | Interface |
|---|---|---|
| Atributos | ✓ (cualquier modificador) | Solo constantes (public static final) |
| Constructores | ✓ | ✗ |
| Métodos abstractos | ✓ (0 o más) | ✓ (todos hasta Java 8) |
| Métodos concretos | ✓ | ✓ (default/static desde Java 8) |
| Herencia múltiple | ✗ (solo una clase) | ✓ (múltiples interfaces) |
| Modificadores | Cualquiera | Solo public (implícitamente) |
Sobrecarga vs Sobrescritura
Juego: Identifica la Diferencia
Arrastra los métodos a la categoría correcta:
Sobrecarga (Overloading)
Mismo nombre de método, diferente firma (parámetros)
Sobrescritura (Overriding)
Mismo nombre y firma en clase hija (herencia)
// SOBRECARGA (OVERLOADING) - En la MISMA clase
public class Calculadora {
// Versión 1: dos enteros
public int sumar(int a, int b) {
return a + b;
}
// Versión 2: tres enteros
public int sumar(int a, int b, int c) {
return a + b + c;
}
// Versión 3: dos doubles
public double sumar(double a, double b) {
return a + b;
}
// Versión 4: array de enteros
public int sumar(int[] numeros) {
int total = 0;
for (int num : numeros) {
total += num;
}
return total;
}
}
// SOBRESCRITURA (OVERRIDING) - En clase HIJA
public class Animal {
public void hacerSonido() {
System.out.println("El animal hace un sonido");
}
}
public class Perro extends Animal {
@Override // Anotación recomendada
public void hacerSonido() {
System.out.println("¡Guau guau!");
}
}
public class Gato extends Animal {
@Override
public void hacerSonido() {
System.out.println("¡Miau miau!");
}
}
// USO POLIMÓRFICO
Animal miAnimal = new Perro();
miAnimal.hacerSonido(); // Output: ¡Guau guau!
Ejercicios Prácticos
Sistema de Biblioteca
Crea un sistema para una biblioteca con las siguientes clases:
- Libro: Clase base con atributos título, autor, ISBN y estado (disponible/prestado)
- LibroDigital: Hereda de Libro, añade formato (PDF, EPUB) y tamaño en MB
- Usuario: Clase con nombre, ID y lista de libros prestados
- Biblioteca: Clase principal que gestiona libros y usuarios
Requisitos: Encapsulamiento, herencia, polimorfismo y sobreescritura de métodos.
Sistema de Figuras Geométricas
Implementa un sistema de figuras geométricas usando interfaces y clases abstractas:
- Interface
Figuracon métodoscalcularArea()ycalcularPerimetro() - Clase abstracta
FiguraGeometricaque implemente algunos métodos comunes - Clases concretas:
Circulo,Rectangulo,Triangulo - Clase
CalculadoraAreasque use polimorfismo
Sistema de Empleados
Crea un sistema de nómina para diferentes tipos de empleados:
- Clase abstracta
Empleadocon atributos básicos y método abstractocalcularSalario() - Clases concretas:
EmpleadoTiempoCompleto,EmpleadoPorHoras,EmpleadoComision - Interface
Bonificablecon métodoaplicarBonificacion() - Sobrecarga de métodos para diferentes tipos de contratación
Juego de Cartas con POO
Implementa un sistema para un juego de cartas usando todos los conceptos de POO:
- Clase
Cartacon valor y palo - Clase abstracta
Jugadorcon estrategias de juego - Interfaces:
Jugable,Barajable - Clase
Mazoque use composición (lista de Cartas) - Sobrecarga para diferentes reglas del juego
- Polimorfismo para diferentes tipos de jugadores
Quiz de Conceptos
Pregunta 1: ¿Qué es una clase en POO?
Resumen y Buenas Prácticas
Conceptos Clave de POO
- Clase: Molde/plano para crear objetos
- Objeto: Instancia concreta de una clase
- Encapsulamiento: Ocultar detalles internos (private + getters/setters)
- Herencia: Reutilizar y extender funcionalidad (extends)
- Polimorfismo: Múltiples formas a través de una interfaz común
- Abstracción: Mostrar solo lo esencial, ocultar complejidad
Buenas Prácticas en POO
- Usa nombres descriptivos para clases y métodos
- Sigue el principio de responsabilidad única
- Prefiere composición sobre herencia cuando sea posible
- Usa modificadores de acceso apropiados
- Documenta tus clases y métodos con JavaDoc
- Usa interfaces para definir contratos claros
- Evita clases demasiado grandes ("god classes")
Errores Comunes
- Olvidar el encapsulamiento (atributos públicos)
- Herencia excesiva (demasiados niveles)
- No usar @Override en sobrescritura
- Confundir sobrecarga con sobrescritura
- Crear clases "todo en uno"
- No validar datos en setters
- Usar herencia para compartir código en lugar de para relaciones "es-un"
Hoja de Referencia Rápida - POO
Definir Clase:
public class MiClase {
private atributo;
public MiClase() {}
public void metodo() {}
}
Herencia:
public class Hijo extends Padre {
@Override
public void metodo() {
super.metodo(); // Llama al padre
}
}
Interface:
public interface MiInterface {
void metodo();
}
public class Clase implements MiInterface {
@Override
public void metodo() {}
}
Abstracta:
public abstract class Abstracta {
public abstract void metodo();
public void concreto() {}
}
Test Final de POO
Pregunta 1 de 5