W3docs

Conceptos de POO en Java

Una visión general de la programación orientada a objetos en Java: encapsulación, herencia, polimorfismo y abstracción.

La programación orientada a objetos (POO) es una forma de organizar el código en torno a las cosas de su programa en lugar de en torno a los pasos. En vez de un largo script que opera sobre variables en bruto, usted describe las clases de objetos de su dominio — un User, una Order, una BankAccount — y da a cada uno los datos y el comportamiento que necesita. El resto del programa entonces pide a esos objetos que hagan cosas, en lugar de hurgar en sus interioridades.

Java se construyó en torno a esta idea. Cada línea de código Java que escribe vive dentro de una clase, y una clase es el plano a partir del cual se fabrican los objetos. Hasta este punto ha estado escribiendo código en su mayoría procedural dentro de main y unos pocos ayudantes estáticos; a partir de esta parte del libro, empieza a diseñar sus propias clases.

Clases y objetos en una frase

Una clase describe una clase de cosa — qué datos contiene y qué puede hacer. Un objeto es una instancia específica de esa cosa.

public class Dog {
  String name;
  int age;

  void bark() {
    System.out.println(name + " says woof");
  }
}

Dog d = new Dog();   // d es un objeto — un perro específico
d.name = "Rex";
d.bark();            // Rex says woof

Dog es la clase. d es un objeto. Puede crear tantos objetos Dog como quiera; cada uno obtiene su propia copia de name y age, y cada uno puede bark() por su cuenta. El capítulo clases y objetos lo desarma en detalle.

Los cuatro pilares

La POO suele enseñarse en torno a cuatro ideas. Cada una recibe un capítulo completo más adelante en esta parte del libro — lo que sigue es un recorrido de treinta segundos para que sepa hacia dónde lleva el camino.

Encapsulación

Mantenga privados los datos de un objeto; exponga en su lugar el comportamiento. El código externo pide account.deposit(50), no account.balance += 50. El beneficio es que la clase controla sus propios invariantes — nadie más puede ponerla en un mal estado.

public class Account {
  private int balance;                          // oculto

  public void deposit(int amount) {             // comportamiento público
    if (amount <= 0) throw new IllegalArgumentException();
    balance += amount;
  }
}

Véase el capítulo encapsulación.

Herencia

Una clase puede extender a otra, adoptando sus campos y métodos y añadiéndoles más. Cat extends Animal reutiliza todo lo que Animal ya hace y solo especifica lo que es distinto en los gatos.

public class Animal {
  void breathe() { System.out.println("inhale, exhale"); }
}
public class Cat extends Animal {
  void purr()   { System.out.println("rrr"); }
}

Cat c = new Cat();
c.breathe();   // heredado
c.purr();      // propio

Véase el capítulo herencia.

Polimorfismo

La misma llamada puede hacer cosas distintas según el objeto real en el extremo receptor. Una variable de tipo Animal podría apuntar a un Cat, un Dog o una Cow — llamar a speak() sobre ella elige el comportamiento correcto en tiempo de ejecución.

Animal a = new Cat();
a.speak();   // llama al speak de Cat, aunque a esté tipada como Animal

Véase el capítulo polimorfismo.

Abstracción

Defina qué hace algo sin comprometerse con el cómo. Una interface Shape dice que toda forma tiene un método area(); cada forma concreta — Circle, Square — aporta su propia fórmula. El código que trabaja con formas no necesita saber qué clase tiene.

public interface Shape {
  double area();
}

Véase el capítulo abstracción.

¿Por qué molestarse?

Para un script de 20 líneas, la POO es excesiva. La recompensa aparece a medida que los programas crecen:

  • Razonamiento local. Una clase BankAccount es dueña de sus reglas. Para entender o cambiar los depósitos, lee el método deposit — no rastrea la base de código en busca de balance +=.
  • Reutilización sin copiar y pegar. La herencia y la composición permiten que SavingsAccount se construya sobre Account en lugar de duplicarlo.
  • Sustituibilidad. Una función que recibe una Shape funciona para cada forma que existe hoy y cada una que añada mañana.
  • Testeabilidad. Los objetos pequeños con responsabilidades claras son fáciles de instanciar, manejar y verificar.

Java está lejos de ser el único lenguaje orientado a objetos — Python, C#, Kotlin, Ruby y muchos otros comparten las mismas ideas con sintaxis diferente. Lo que aprende en esta parte es transferible.

La POO no es el único paradigma

Incluso dentro de Java, ya ha escrito código que no es estrictamente OO: métodos de utilidad estáticos, matemáticas con primitivos, simple flujo de control. El Java moderno mezcla paradigmas — canalizaciones funcionales con streams y lambdas, datos inmutables con records, trabajo declarativo con anotaciones. La POO es la columna vertebral del lenguaje, no una jaula. Use una clase cuando modele una cosa con estado y comportamiento; recurra a un método estático cuando solo necesite un cálculo.

Un ejemplo trabajado

El código completo de los fragmentos anteriores, reunido para que pueda ejecutarlo:

java— editable, runs on the server

Qué sigue

Ahora que conoce la forma de la POO, el siguiente capítulo fija sus fundamentos: cómo una definición de clase se convierte en un objeto en memoria, qué hace realmente new y en qué se diferencian las referencias a objetos de los primitivos. Continúe a Clases y objetos de Java.

Práctica

Práctica

¿Qué afirmación describe mejor la diferencia entre una clase y un objeto?