Una clase es la definición de un tipo con estado y comportamiento, mientras que un objeto es una instancia concreta de esa clase.
Hasta este punto del curso, hemos estado programando de forma estructurada. Usábamos tipos de datos que Java nos daba (int, double, arrays) y escribíamos instrucciones una detrás de otra.
Pero el mundo real no se compone solo de números y letras. El mundo está lleno de cosas complejas: Usuarios, Coches, Facturas, Enemigos de un videojuego.
Un int no sirve para representar a un “Usuario”. Un usuario tiene nombre, correo, edad y comportamientos (loguearse, comprar). Necesitamos crear nuestros propios tipos de datos.
Bienvenidos a la Programación Orientada a Objetos (POO).
¿Qué es una clase y qué es un objeto?
Esta es la distinción fundamental. Si no entiendes esto, no entiendes Java.
Una Clase es una plantilla, un molde o un plano. No existe en el mundo físico. Es solo una definición teórica de cómo debería ser algo.
- Ejemplo: El plano arquitectónico de una casa. El plano dice dónde van las ventanas, pero no puedes vivir en el plano.
Un Objeto, o instancia, es la materialización de esa clase. Es algo concreto que ocupa espacio en la memoria (en el Heap).
- Ejemplo: La casa construida en la calle Mayor nº 5. Puedes entrar y vivir. Con un solo plano (Clase) puedes construir 100 casas diferentes (Objetos).
Definiendo una clase en Java
Vamos a crear nuestra primera clase. Por convención, las clases en Java empiezan siempre por Mayúscula y cada clase suele ir en su propio archivo .java.
Una clase se compone de dos cosas:
- Atributos (Estado): Variables que guardan datos (sustantivos).
- Métodos (Comportamiento): Funciones que hacen cosas (verbos).
// Archivo: Robot.java
public class Robot {
// 1. Atributos (Variables de instancia)
// Describen "cómo es" el objeto
String nombre;
int nivelBateria;
// 2. Métodos
// Describen "qué puede hacer" el objeto
public void saludar() {
System.out.println("Hola, soy " + nombre + " y tengo " + nivelBateria + "% de energía.");
}
public void cargar() {
nivelBateria = 100;
System.out.println("Carga completa. Bip bip.");
}
}Instanciación: la palabra clave new
Tener el código de arriba no hace nada por sí solo. Es solo papel mojado. Para usarlo, necesitamos crear objetos. A este proceso se le llama Instanciar.
Para crear una instancia usamos la palabra clave new.
// Archivo: Main.java
public class Main {
public static void main(String[] args) {
// Declaración (Stack) = Instanciación (Heap)
Robot r1 = new Robot();
// Configurando el objeto 1
r1.nombre = "Wall-E";
r1.nivelBateria = 50;
// Creando un SEGUNDO objeto totalmente independiente
Robot r2 = new Robot();
r2.nombre = "R2-D2";
r2.nivelBateria = 85;
// Usando sus comportamientos
r1.saludar(); // "Hola, soy Wall-E..."
r2.saludar(); // "Hola, soy R2-D2..."
}
}¿Qué hace new realmente?
Cuando escribes new Robot(), ocurren tres pasos críticos en la memoria:
- Reserva: Java busca espacio libre en el Heap suficiente para guardar un
Stringy unint. - Inicialización: Se asignan valores por defecto a los atributos (o se ejecuta el constructor, que veremos en el siguiente artículo).
- Referencia: Devuelve una referencia al objeto y la asigna a la variable
r1.
El operador punto (.)
Seguro que te has fijado en r1.nombre o r1.saludar().
El punto es el operador de acceso.
Léelo como: “Ve al objeto al que apunta la variable r1 y dentro de él accede al atributo nombre”.
Gracias a esto, r1.nombre y r2.nombre son variables distintas, aunque se llamen igual, porque pertenecen a instancias diferentes.
El ciclo de vida de un objeto
En el mundo real, las cosas nacen, crecen y mueren. En Java, también.
Nacimiento (creation)
Ocurre cuando se ejecuta el new. El objeto cobra vida en el Heap.
Vida (in use)
El objeto puede seguir utilizándose mientras sea alcanzable desde alguna referencia activa. No basta con contar variables: también puede estar conectado a otros objetos alcanzables.
Robot r3 = new Robot(); // Nace
Robot r4 = r3; // Ahora r4 también apunta al mismo robotMuerte y el garbage collector
Aquí Java brilla con luz propia.
En lenguajes antiguos (C++), si creabas un objeto, tenías que destruirlo manualmente (delete). Si se te olvidaba, la memoria se llenaba (Memory Leak) y el programa crasheaba.
En Java, existe un proceso automático llamado Garbage Collector (Recolector de Basura).
Cuando un objeto deja de ser alcanzable, queda disponible para que el garbage collector recupere su memoria. No hay garantía de que lo haga inmediatamente.
r3 = null; // Rompemos el mando r3
r4 = null; // Rompemos el mando r4
// En este momento, el objeto Robot que creamos está "perdido" en el Heap.
// Nadie puede acceder a él.
// El Garbage Collector pasará, lo verá y borrará su memoria. RIP.