Netbeans overrideable method call in constructor
Cảnh báo phương thức có thể override được gọi trong phương thức khởi tạo (ở Netbeans)

Có khi nào bạn code gặp cái cảnh báo như thế này chưa? Có lẽ cũng đã đôi lần gặp rồi nhỉ. Liệu bạn có tự hỏi tại sao nó lại báo lỗi như vậy? Mình cũng đã từng có thắc mắc và không hiểu. Mình chỉ hiểu được khi mình thực sự gặp rắc rối với nó.

Bài viết này mình sẽ giải thích lí do vì sao cần phải tránh Overridable method call in constructor trong lập trình hướng đối tượng.

Xét ví dụ nhỏ gây nhầm lẫn (Ngôn ngữ Java)

/**
 *
 * @author Diep Esc
 */
public class Parent {

    public Parent() {
        createParams();
    }

    public void createParams() {

    }
}

class Child extends Parent {

    private int param = 2;

    @Override
    public void createParams() {
        param = param * 2;
        System.out.println(“params were created”);
    }

    public static void main(String[] args) {
        Child obj = new Child();
        System.out.println(“param is ” + obj.param);
    }
}

Một ví dụ gây nhầm lẫn khi Overridable method call in constructor

Bạn thử đoán xem khi chạy đoạn code bên trên, kết quả xuất ra param bằng bao nhiêu? Có lẽ là 4 chăng? Không phải, nó là 2. Tại sao vậy?

Lí giải kết quả

Trong lập trình hướng đối tượng, lời gọi đến constructor của class cha luôn được đặt đầu tiên trong constructor của lớp con. Nếu trong code không chỉ định constructor nào thì constructor mặc định sẽ được chọn. Có thể nói class Child ở ví dụ trên có constructor như sau:

    public Child(){
        super();
    }

Constructor mặc định

Tức là lời gọi super được thực hiện trước tiên. Nó được gọi trước cả lệnh gán param = 2; ở dòng số 18 trong ví dụ. Trong khi đó constructor của lớp cha lại gọi đến phương thức createParams.  Do đó  createParams cũng được thực hiện trước. Lệnh gán ở dòng số 18 thực hiện sau nên kết quả sau cùng là param = 2.

Đối với những dự án thực tế

Đối với các dự án thực tế, logic của nó sẽ phức tạp hơn nhiều so với ví dụ mà mình đã  đưa ra ở bên trên. Do đó việc hạn chế những nhầm lẫn không đáng có là cần thiết. Có thể bạn tự tin mình hiểu và không nhầm lẫn. Nhưng ở dự án thực tế, thường có nhiều người làm chung. Khi bạn viết class cha, bạn không biết những ai sẽ viết những class con, và họ xử lí như thế nào, họ có rơi vào tình huống gây nhầm lẫn hay không.

Vậy nên, những phương thức (của cùng class) được gọi ở constructor không nên overridable (dùng private hoặc final, static). Còn nếu phương thức cần là overriable thì nên tách ra, gọi ở nơi khác thay vì constructor. Ngoài ra, trong trường hợp constructor gọi đến 1 phương thức non-overridable, phương thức non-overridable đó lại gọi đến 1 phương thức khác overridable, thì cũng có thể gây nên nhầm lẫn như ví dụ ở bên trên. Do đó trường hợp này cũng nên chú ý tránh mắc phải.