Encadenamiento de constructores
Parte de la sección Programación Orientada a Objetos del Journey de Java de Coddy — lección 23 de 87.
El encadenamiento de constructores (constructor chaining) es el proceso de llamar a un constructor desde otro. Esta técnica ayuda a evitar la duplicación de código cuando una clase tiene múltiples constructores o cuando se trabaja con jerarquías de herencia.
Dentro de la misma clase, puedes encadenar constructores usando this(). Esto te permite tener un constructor "principal" que realiza todo el trabajo, mientras que otros constructores simplemente delegan en él:
public class Rectangle {
private int width;
private int height;
public Rectangle() {
this(1, 1); // Llama al constructor de dos parámetros
}
public Rectangle(int size) {
this(size, size); // Crea un cuadrado
}
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
}En la herencia, el encadenamiento de constructores ocurre automáticamente. Cuando creas un objeto de una subclase, Java llama primero al constructor del padre usando super(). Si no llamas explícitamente a super(), Java inserta super() (la versión sin argumentos) automáticamente:
public class Animal {
private String name;
public Animal(String name) {
this.name = name;
System.out.println("Animal constructor");
}
}
public class Dog extends Animal {
private String breed;
public Dog(String name, String breed) {
super(name); // Debe ser la primera línea
this.breed = breed;
System.out.println("Dog constructor");
}
}Al crear new Dog("Buddy", "Labrador") se imprime primero "Animal constructor" y luego "Dog constructor". Esto asegura que las clases padre siempre se inicialicen correctamente antes de que la clase hija añada su propia configuración.
Desafío
FácilVamos a construir un sistema de pedidos de productos que demuestre el encadenamiento de constructores tanto dentro de una clase como a través de una jerarquía de herencia. Verás cómo this() encadena constructores en la misma clase, mientras que super() se encadena con los constructores del padre.
Crearás tres archivos para organizar tu código:
Product.java: Crea una clase padre que represente cualquier producto en una tienda. Debe tener:- Campos privados para
name(String) yprice(double) - Un constructor principal que reciba tanto el nombre como el precio, inicialice los campos e imprima:
"Product constructor: " + name - Un segundo constructor que reciba solo el nombre y se encadene al constructor principal usando
this(name, 0.0)para establecer un precio por defecto de 0.0 - Métodos
getName()ygetPrice()para acceder a los campos
- Campos privados para
Electronics.java: Crea una subclase que extienda de Product y añada información de garantía:- Un campo privado para
warrantyYears(int) - Un constructor principal que reciba name, price y warrantyYears - usa
super(name, price)para inicializar al padre, luego establece la garantía e imprime:"Electronics constructor: " + warrantyYears + " year warranty" - Un segundo constructor que reciba solo name y price, encadenándose al constructor principal con
this(name, price, 1)para proporcionar una garantía por defecto de 1 año - Un tercer constructor que reciba solo el nombre, encadenándose al segundo constructor con
this(name, 0.0) - Un método
getDetails()que devuelva:getName() + " - $" + String.format("%.2f", getPrice()) + " (" + warrantyYears + " year warranty)"
- Un campo privado para
Main.java: Demuestra el encadenamiento de constructores en acción. Recibirás tres entradas: un nombre de producto (String), precio (double) y años de garantía (int). Crea un objeto Electronics usando los tres parámetros, luego imprime el resultado degetDetails().
Recibirás tres entradas: el nombre del producto, el precio y los años de garantía.
Formatea el precio en getDetails() para mostrar 2 decimales usando String.format("%.2f", getPrice()). Observa la salida con atención: ¡verás aparecer los mensajes de los constructores en orden, mostrando cómo fluye la cadena de padre a hijo!
Hoja de referencia
El encadenamiento de constructores es el proceso de llamar a un constructor desde otro para evitar la duplicación de código.
Encadenamiento dentro de la misma clase
Use this() para llamar a otro constructor en la misma clase:
public class Rectangle {
private int width;
private int height;
public Rectangle() {
this(1, 1); // Llama al constructor de dos parámetros
}
public Rectangle(int size) {
this(size, size); // Crea un cuadrado
}
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
}Encadenamiento en la herencia
Use super() para llamar al constructor de la clase padre. Debe ser la primera línea en el constructor:
public class Animal {
private String name;
public Animal(String name) {
this.name = name;
System.out.println("Animal constructor");
}
}
public class Dog extends Animal {
private String breed;
public Dog(String name, String breed) {
super(name); // Debe ser la primera línea
this.breed = breed;
System.out.println("Dog constructor");
}
}Si no llama explícitamente a super(), Java inserta automáticamente super() (la versión sin argumentos). Los constructores de los padres siempre se llaman antes que los constructores de los hijos, lo que garantiza un orden de inicialización adecuado.
Pruébalo tú mismo
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Leer entradas
String name = scanner.nextLine();
double price = scanner.nextDouble();
int warrantyYears = scanner.nextInt();
// TODO: Crear un objeto Electronics usando los tres parámetros
// TODO: Imprimir el resultado de getDetails()
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosIntroducción a la OOPClases vs. ObjetosLa palabra clave thisMétodosCampos (Atributos)Método constructorSobrecarga de constructoresResumen - Calculadora simple4Herencia
Herencia básica (extends)La palabra clave superSobrescritura de métodos (@Override)Encadenamiento de constructoresLa clase ObjectHerencia simple y multinivelPor qué no hay herencia múltiple de clasesResumen - Jerarquía de empleados7Métodos especiales y la clase Object
Método toString()equals() y hashCode()Método clone()compareTo() y ComparableInterfaz ComparatorResumen - Ordenamiento personalizado2Modificadores de acceso y encapsulamiento
Visión general de los niveles de accesoMétodos Getter y SetterOcultamiento de informaciónLa palabra clave finalResumen - Gestor de cuentas bancarias5Polimorfismo
Fundamentos de sobrecarga de métodosSobrescritura de métodos (tiempo de ejecución)Upcasting y DowncastingEl operador instanceofClases y métodos abstractosResumen - Calculadora de figuras8Conceptos avanzados de POO
Composición vs. HerenciaAgregación vs. ComposiciónClases internas, anidadas y anónimasEnums y métodos de EnumRecords (Java 16+)Clases selladas (Java 17+)11Patrones de diseño - Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón BuilderPatrón ObserverPatrón Strategy3Propiedades de clase y miembros estáticos
Variables de instancia vs. estáticasMétodos estáticosBloques estáticosConstantes (static final)Repaso - Contador y utilidad6Interfaces y Clases Abstractas
Introducción a las InterfacesImplementación de InterfacesImplementación de Múltiples InterfacesMétodos Default y Static en InterfacesClases Abstractas vs InterfacesInterfaces FuncionalesResumen - Sistema de Pagos9Genéricos
Introducción a los genéricosClases genéricasMétodos genéricosParámetros de tipo delimitadosComodines (?, extends, super)Resumen - Contenedor genérico12Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Iterator