Constructores y this
En resumen: Un constructor es un método especial con el nombre de la clase que se ejecuta con new y rellena los campos del objeto nuevo, y this es el propio objeto.
Problema
Un café de 0 €
Creas un producto, igual que en la lección anterior, y rellenas los campos línea por línea. Se te olvidó una línea:
Product coffee = new Product();coffee.name = "Café";coffee.quantity = 2;System.out.println(coffee.name + ": " + coffee.price * coffee.quantity + " €");Café: 0.0 €El café cuesta 0 €. El compilador no se queja: para él, el precio tiene un valor, 0. Cuantos más campos tiene una clase, más fácil es saltarse uno. Y un producto sin precio ni siquiera debería poder existir.
La idea
Constructor: sin estos datos no hay objeto
Una clase puede decir qué necesita antes de que puedas crear un objeto a partir de ella. Para eso sirve el constructor: un método especial que se ejecuta con new.
class Product { public String name; public double price; public int quantity;
public Product(String name, double price, int quantity) { this.name = name; this.price = price; this.quantity = quantity; }}
public class Main { public static void main(String[] args) { Product coffee = new Product("Café", 7.50, 2); System.out.println(coffee.name + ": " + coffee.price * coffee.quantity + " €"); }}Café: 15.0 €- El constructor tiene exactamente el mismo nombre que la clase:
Product. - No tiene tipo de retorno, ni siquiera
void. - Sus parámetros son los datos sin los que un producto no puede existir. Los pasas en los paréntesis de
new:new Product("Café", 7.50, 2).
Ahora no hay forma de olvidar el precio. Si pasas dos argumentos en lugar de tres, el programa no compila.
public Product(String name, double price, int quantity) { this.name = name; this.price = price; this.quantity = quantity;}
Product coffee = new Product("Café", 7.50, 2);System.out.println(coffee.name + ": " + coffee.price * coffee.quantity + " €");Paso a paso, en palabras
- new reserva un objeto nuevo. Sus campos tienen valores por defecto.
- Se ejecuta el constructor. Los argumentos se copian en sus parámetros.
- this.name = name: del parámetro al campo de este objeto.
- Lo mismo para el precio y la cantidad.
- El constructor termina y los parámetros desaparecen. coffee recibe una flecha al objeto terminado.
- El objeto sale de new ya rellenado, así que el precio no es 0.
La idea
this: el campo de este objeto
Dentro del constructor hay dos cosas que se llaman name: el parámetro y el campo. El nombre solo es el parámetro, porque está «más cerca». Para el campo escribes this.name.
public Product(String name, double price, int quantity) { this.name = name; this.price = price; this.quantity = quantity;}this es el objeto que se está creando ahora mismo. this.name = name; significa «guarda el parámetro name en el campo name de este objeto».
Los parámetros podrían tener otros nombres (productName), y entonces no necesitarías this. Pero en Java los nombres iguales son habituales, porque se ve enseguida qué parámetro va a qué campo.
Pruébalo
Encuentra el error
Elige la línea con el error.
name = name; guarda el parámetro en sí mismo. El campo se queda en null. Necesitas this.name = name;. El compilador no da ningún error, así que un error así es difícil de detectar.
La idea
¿Y el new Product() de la lección anterior?
En la lección anterior no había constructor, y new Product() funcionaba. Si no escribes un constructor, el compilador añade uno vacío, sin parámetros. Se llama constructor por defecto, y deja los campos con sus valores por defecto.
En cuanto escribes tu propio constructor, el vacío desaparece:
Product empty = new Product();error: constructor Product in class Product cannot be applied to given types;De eso se trata: ya no se puede crear un producto sin nombre ni precio. Si aun así necesitas un constructor vacío, escríbelo tú.
La idea
Varios constructores
La mayoría de los productos del carrito van de uno en uno. Escribir 1 cada vez cansa.
Puedes darle a la clase un segundo constructor, sin la cantidad. Va junto al primero:
public Product(String name, double price) { this.name = name; this.price = price; this.quantity = 1;}Es la sobrecarga del módulo «Métodos»: un nombre, parámetros distintos. Con new, el compilador elige el constructor según los argumentos.
Más precisamente, para curiosos
Los dos constructores repiten las mismas líneas. En lugar de eso, el más corto puede llamar al más largo:
public Product(String name, double price) { this(name, price, 1);}this(...) llama a otro constructor de la misma clase. Tiene que ser la primera línea del constructor.
Así, si mañana añades una comprobación del precio, la escribes en un solo constructor.
Pruébalo
¿Qué constructor?
¿Qué imprimirá el programa?
class Product { public String name; public double price; public int quantity;
public Product(String name, double price) { this.name = name; this.price = price; this.quantity = 1; }
public Product(String name, double price, int quantity) { this.name = name; this.price = price; this.quantity = quantity; }}
Product bread = new Product("Pan", 1.20);Product milk = new Product("Leche", 2.10, 3);System.out.println(bread.quantity + " " + milk.quantity);new Product("Pan", 1.20) tiene dos argumentos, así que se llama al constructor con dos parámetros. Guarda una cantidad de 1. Para la leche se pasan tres argumentos, así que se llama al otro constructor.Pruébalo
¿Cómo se llama el constructor?
¿Qué va en el hueco?
class Book {
public String title;
public String author;
public (String title, String author) {
this.title = title;
this.author = author;
}
}Book: el constructor tiene exactamente el mismo nombre que la clase, con la misma mayúscula.Ejercicio
Objetos creados completos
Resuélvelos en tu editor. Cada clase recibe un constructor con parámetros para todos sus campos.
1. Persona. Una clase Person con un nombre y una edad. Crea dos personas e imprime sus datos.
María, 34 añosPablo, 19 años2. Animal. Una clase Animal con una especie y una edad. Crea un gato de 3 años y un perro de 7.
Especie: gato, edad: 3Especie: perro, edad: 73. Paso de baile. Una clase DanceMove con un nombre y una duración en segundos. En la lección «Métodos de instancia», el paso aprenderá a «ejecutarse» solo.
moonwalk: 5 sMás práctica
- Un libro con constructor. Reescribe
Bookde la lección anterior con un constructorBook(title, author). ¿Cuántas líneas ahorraste en main? -
Un producto con dos constructores.
Productcon dos constructores, como en la lección. Haz un array{ new Product("Pan", 1.20, 2), new Product("Café", 7.50) }e imprime el nombre y la cantidad de cada uno: «Pan x2», «Café x1». Después haz que el constructor más corto llame al más largo. - Reserva. Una clase
Bookingcon el nombre del huésped, el número de noches y el precio por noche. Imprime cuánto cuesta la estancia: 3 noches a 85 € son 255 €.
Test
Ponte a prueba
Lecciones relacionadas
Sección «Lecciones relacionadas»- Se basa en: Métodos · Parámetros y return · Sobrecarga · Clases y objetos
- Continúa en: Métodos de instancia · Encapsulamiento · static: lo que comparten todos los objetos · Herencia
- Ejercicios sobre el tema: Clases y objetos