Menu
CoddyTech

Chuỗi gọi hàm khởi tạo

Thuộc phần Lập trình hướng đối tượng trong hành trình Java của Coddy. Bài học 23 trên 87.

Gọi nối tiếp hàm khởi tạo (constructor chaining) là quá trình gọi một hàm khởi tạo từ một hàm khởi tạo khác. Kỹ thuật này giúp tránh lặp lại code khi một lớp có nhiều hàm khởi tạo hoặc khi làm việc với các hệ thống phân cấp kế thừa.

Trong cùng một lớp, bạn có thể gọi nối tiếp các hàm khởi tạo bằng this(). Cách này cho phép bạn có một hàm khởi tạo “chính” xử lý mọi việc, còn các hàm khởi tạo khác chỉ chuyển tiếp đến hàm đó:

public class Rectangle {
    private int width;
    private int height;
    
    public Rectangle() {
        this(1, 1);  // Gọi hàm khởi tạo có hai tham số
    }
    
    public Rectangle(int size) {
        this(size, size);  // Tạo một hình vuông
    }
    
    public Rectangle(int width, int height) {
        this.width = width;
        this.height = height;
    }
}

Trong kế thừa, việc gọi chuỗi hàm khởi tạo diễn ra tự động. Khi bạn tạo một đối tượng của lớp con, Java gọi hàm khởi tạo của lớp cha trước bằng super(). Nếu bạn không gọi rõ ràng super(), Java tự động chèn super() (phiên bản không có đối số):

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);  // Phải là dòng đầu tiên
        this.breed = breed;
        System.out.println("Dog constructor");
    }
}

Việc tạo new Dog("Buddy", "Labrador") sẽ in ra "Animal constructor" trước, rồi đến "Dog constructor". Nhờ vậy, các lớp cha luôn được khởi tạo đúng cách trước khi lớp con thêm phần thiết lập riêng.

challenge icon

Thử thách

Dễ

Hãy xây dựng một hệ thống đặt hàng sản phẩm để minh họa cách gọi chuỗi hàm khởi tạo trong cùng một lớp và qua hệ thống kế thừa. Bạn sẽ thấy cách this() gọi chuỗi hàm khởi tạo trong cùng lớp, còn super() gọi hàm khởi tạo của lớp cha.

Bạn sẽ tạo ba tệp để sắp xếp code:

  • Product.java: Tạo một lớp cha đại diện cho mọi sản phẩm trong cửa hàng. Lớp này cần có:
    • Các trường private cho name (String) và price (double)
    • Một hàm khởi tạo chính nhận cả tên và giá, khởi tạo các trường, rồi in ra: Product constructor: [name]
    • Một hàm khởi tạo thứ hai chỉ nhận tên và gọi chuỗi hàm khởi tạo chính bằng this(name, 0.0) để đặt giá mặc định là 0.0
    • Các phương thức getName() và getPrice() để truy cập các trường
  • Electronics.java: Tạo một lớp con kế thừa Product và bổ sung thông tin bảo hành:
    • Một trường private cho warrantyYears (int)
    • Một hàm khởi tạo chính nhận tên, giá và warrantyYears, dùng super(name, price) để khởi tạo lớp cha, sau đó đặt thời hạn bảo hành và in ra: Electronics constructor: [warrantyYears] year warranty
    • Một hàm khởi tạo thứ hai chỉ nhận tên và giá, gọi chuỗi hàm khởi tạo chính bằng this(name, price, 1) để đặt thời hạn bảo hành mặc định là 1 năm
    • Một hàm khởi tạo thứ ba chỉ nhận tên, gọi chuỗi hàm khởi tạo thứ hai bằng this(name, 0.0)
    • Một phương thức getDetails() trả về: [name] - $[price] ([warrantyYears] year warranty)
  • Main.java: Minh họa cách gọi chuỗi hàm khởi tạo. Bạn sẽ nhận ba đầu vào: tên sản phẩm (String), giá (double) và số năm bảo hành (int). Tạo một đối tượng Electronics bằng cả ba tham số, rồi in ra kết quả của getDetails().

Bạn sẽ nhận ba đầu vào: tên sản phẩm, giá và số năm bảo hành.

Định dạng giá trong getDetails() để hiển thị 2 chữ số thập phân bằng String.format("%.2f", price). Hãy theo dõi kỹ đầu ra, bạn sẽ thấy các thông báo của hàm khởi tạo xuất hiện theo thứ tự, cho thấy chuỗi gọi chạy từ lớp cha đến lớp con!

Tự làm thử

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Đọc các đầu vào
        String name = scanner.nextLine();
        double price = scanner.nextDouble();
        int warrantyYears = scanner.nextInt();
        
        // TODO: Tạo đối tượng Electronics bằng cả ba tham số
        
        // TODO: In ra kết quả của getDetails()
    }
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch Java online