Clases y Objetos en Java

Clases y Objetos en Java

1. Introducción

En este breve tutorial, examinaremos dos bloques fundamentales del lenguaje de programación Java: clases y objetos. Son conceptos básicos de la Programación Orientada a Objetos (OOP, por sus siglas en inglés), que utilizamos para modelar entidades de la vida real.

En la OOP, las clases son planos o plantillas para objetos. Las usamos para describir tipos de entidades.

Por otro lado, los objetos son entidades vivas, creadas a partir de clases. Contienen ciertos estados en sus campos y presentan ciertos comportamientos con sus métodos.

2. Clases

En pocas palabras, una clase representa una definición o un tipo de objeto. En Java, las clases pueden contener campos, constructores y métodos.

Veamos un ejemplo utilizando una simple clase Java que representa un Coche:

class Coche {

    // campos
    String tipo;
    String modelo;
    String color;
    int velocidad;

    // constructor
    Coche(String tipo, String modelo, String color) {
        this.tipo = tipo;
        this.modelo = modelo;
        this.color = color;
    }
    
    // métodos
    int incrementarVelocidad(int incremento) {
        this.velocidad = this.velocidad + incremento;
        return this.velocidad;
    }
    
    // ...
}

Esta clase Java representa un automóvil en general. Podemos crear cualquier tipo de automóvil a partir de esta clase. Utilizamos campos para mantener el estado y un constructor para crear objetos a partir de esta clase.

Cada clase Java tiene un constructor vacío por defecto. Lo utilizamos si no proporcionamos una implementación específica como hicimos anteriormente. Así es cómo se vería el constructor por defecto para nuestra clase Coche:

Coche(){}

Este constructor simplemente inicializa todos los campos del objeto con sus valores por defecto. Las Strings se inicializan como null y los enteros como cero.

Ahora bien, nuestra clase tiene un constructor específico porque queremos que nuestros objetos tengan sus campos definidos cuando los creamos:

Coche(String tipo, String modelo) {
    // ...
}

En resumen, escribimos una clase que define un automóvil. Sus propiedades se describen mediante campos, que contienen el estado de los objetos de la clase, y su comportamiento se describe mediante métodos.

3. Objetos

Mientras que las clases se traducen durante el tiempo de compilación, los objetos se crean a partir de clases en tiempo de ejecución.

A los objetos de una clase se les llama instancias, y los creamos e inicializamos con constructores:

Coche fiesta = new Coche("Ford", "Fiesta", "amarillo");
Coche panda = new Coche("Seat", "Panda", "rojo");
Coche taycan = new Coche("Porsche", "Taycan", "negro");

Ahora hemos creado diferentes objetos Coche, todos a partir de una única clase. Este es el punto de todo esto, definir el plano en un solo lugar y luego reutilizarlo muchas veces en muchos lugares.

Hasta ahora, tenemos tres objetos Coche, y todos están estacionados ya que su velocidad es cero. Podemos cambiar esto invocando nuestro método incrementarVelocidad:

fiesta.incrementarVelocidad(10);
panda.incrementarVelocidad(20);
golf.incrementarVelocidad(30);

Ahora hemos cambiado el estado de nuestros automóviles: todos se están moviendo a diferentes velocidades.

Además, podemos y debemos definir el control de acceso para nuestra clase, sus constructores, campos y métodos. Podemos hacerlo utilizando modificadores de acceso, como veremos en la siguiente sección.

4. Modificadores de Acceso

En los ejemplos anteriores, omitimos modificadores de acceso para simplificar el código. Al hacerlo, en realidad utilizamos un modificador predeterminado de nivel de paquete. Ese modificador permite el acceso a la clase desde cualquier otra clase en el mismo paquete.

Por lo general, usamos un modificador public para los constructores para permitir el acceso desde todos los demás objetos:

public Coche(String tipo, String modelo, String color) {
    // ...
}

Cada campo y método en nuestra clase también debería haber definido control de acceso mediante un modificador específico. Las clases suelen tener modificadores public, pero tendemos a mantener nuestros campos private.

Los campos contienen el estado de nuestro objeto, por lo tanto, queremos controlar el acceso a ese estado. Podemos mantener algunos de ellos private y otros public. Logramos esto con métodos específicos llamados 'getters' y 'setters'.

Echemos un vistazo a nuestra clase con un control de acceso completamente especificado:

public class Coche {
    private String tipo;
    // ...

    public Coche(String tipo, String modelo, String color) {
       // ...
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getVelocidad() {
        return velocidad;
    }

    // ...
}

Nuestra clase está marcada como public, lo que significa que podemos usarla en cualquier paquete. Además, el constructor es public, lo que significa que podemos crear un objeto a partir de esta clase dentro de cualquier otro objeto.

Nuestros campos están marcados como private, lo que significa que no son accesibles directamente desde nuestro objeto, pero proporcionamos acceso a través de getters y setters.

Los campos de tipo y modelo no tienen getters y setters, porque contienen datos internos de nuestros objetos. Solo podemos definirlos a través del constructor durante la inicialización.

Además, el color se puede acceder y cambiar, mientras que la velocidad solo se puede acceder, pero no cambiar. Hemos aplicado ajustes de velocidad a través de métodos public especializados incrementarVelocidad() y decrementarVelocidad().

En otras palabras, utilizamos el control de acceso para encapsular el estado del objeto.

5. Conclusión

En este artículo, hemos repasado dos elementos básicos del lenguaje Java, las clases y los objetos, y hemos mostrado cómo y por qué se utilizan. También hemos introducido los conceptos básicos del control de acceso y hemos demostrado su uso.