2013-02-01 59 views
6

Tôi rất bối rối với Overriding Constructors. Constructor không thể được ghi đè là kết quả những gì tôi nhận được khi tôi đã tìm kiếm nó trong google câu hỏi của tôi làOverriding Constructors

public class constructorOverridden { 

    public static void main(String args[]) { 
     Sub sub = new Sub(); 
     sub.test(); 
    } 
} 

class Super { 
    Super() { 
     System.out.println("In Super constructor"); 
     test(); 
    } 

    void test() { 
     System.out.println("In Super.test()"); 
    } 
} 

class Sub extends Super { 
    Sub() { 
     System.out.println("In Sub constructor"); 
    } 

    void test() { // overrides test() in Super 
     System.out.println("In Sub.test()"); 
    } 
} 

khi tôi chạy này tôi đã nhận được kết quả như

In Super constructor 
In Sub.test() 
In Sub constructor 
In Sub.test() 

xin lưu ý các phương pháp thử nghiệm trong lớp được thực hiện. Nó cho thấy rằng constructor Superclass được ghi đè. Liệu nó có đúng không?

Trả lời

19

Các nhà xây dựng không đa hình - bạn hoàn toàn không ghi ghi đè. Bạn tạo các hàm tạo mới trong lớp con và mỗi hàm tạo của lớp con phải chuỗi (có thể gián tiếp) cho một hàm tạo siêu lớp. Nếu bạn không ràng buộc một cách rõ ràng với một hàm tạo, một lời gọi ngầm tới hàm tạo lớp cha không có tham số được chèn vào phần đầu của cơ cấu hàm tạo của lớp con.

Hiện tại về phương pháp ghi đè phương pháp - đối tượng là "loại cuối cùng" ngay từ đầu, kể cả khi thực thi hàm tạo siêu lớp. Vì vậy, nếu bạn in getClass() trong mã xây dựng Super, bạn sẽ vẫn thấy Sub ở đầu ra. Kết quả là phương pháp ghi đè (tức là Sub.test) được gọi, mặc dù hàm tạo Sub vẫn chưa được thực thi. Đây là cơ bản là một ý tưởng tồi, và bạn hầu như luôn tránh gọi các phương thức có khả năng bị ghi đè trong các nhà xây dựng - hoặc tài liệu rất rõ ràng rằng nó sẽ là trường hợp (để mã lớp con biết rằng nó có thể ' t dựa vào các biến đã được khởi tạo một cách thích hợp, vv).

+0

Sau đó, cách tiếp cận nào nên được sử dụng khi tránh "gọi các phương thức ghi đè trong nhà thầu"? Những gì tôi đã cố gắng thực hiện là luồng cơ bản trong một hàm tạo lớp siêu gọi phương thức trừu tượng init(), build() rồi điền(). Vì vậy, tất cả các lớp phụ phải trải qua cùng một luồng! – Akshat

+0

@Akshat: Vâng, có vẻ như nó rơi vào danh mục "tài liệu rất rõ ràng". Thông thường có một số cách thiết kế xung quanh điều này, nhưng thật khó để đưa ra một công thức chung. –

+0

Nếu bạn chỉ có thể cung cấp liên kết cho những cách đó, điều đó thật tuyệt vời! – Akshat

3

Dòng đầu tiên tiềm ẩn của một hàm tạo là một cuộc gọi đến Super(). Đó là lý do tại sao bạn nhận được những kết quả đó.

3

Chính xác. Khi khởi tạo một lớp con, hàm tạo của lớp bậc trên được gọi là đầu tiên, và sau đó mỗi hàm tạo liên tiếp trong cấu trúc phân cấp.

Trong ví dụ trên, trình tạo lớp bậc trên gọi phương thức ghi đè (test()). Điều này làm việc, nhưng có khả năng nguy hiểm vì hàm tạo lớp con chưa được gọi, và lớp con của bạn sẽ không được khởi tạo đầy đủ. Vì lý do này, việc gọi các phương thức ghi đè (hoặc overriddable) trong một hàm tạo không phải là thực hành tốt.

2

nó không ghi đè hàm tạo và lớp khởi tạo siêu lớp không thể bị ghi đè nó có thể bị quá tải.

Khi bạn tạo lớp siêu đối tượng lớp con sẽ được khởi tạo trước tiên thì lớp con sẽ được khởi tạo. Nó giống như Trẻ em không thể tồn tại mà không có cha mẹ.

Trình biên dịch sẽ tự động gọi hàm tạo siêu lớp từ hàm tạo lớp con.

Sub() { 
    super(); 
    System.out.println("In Sub constructor"); 
} 
4

Bạn không thể ghi đè hàm tạo làm hàm tạo được gọi bằng tên của lớp mà nó tạo. Làm thế nào bạn có thể tạo ra một số lớp khác nhau với cùng một hàm tạo? Ngoài ra, một lớp con không kế thừa các hàm tạo từ cha mẹ của nó.

Nếu constructor mẹ hiện một số khởi tạo quan trọng, nó có thể được gọi từ các nhà xây dựng con sử dụng siêu:

class Err extends Throwable { 
    Err(String message) { 
     super(message); // Call the constructor of Throwable. 
     .. 

Phụ huynh constructor lớp cũng luôn gọi. Nếu bản thân bạn không gọi bất kỳ, một hàm tạo không có tham số được gọi tự động trước khi nhập một hàm tạo của lớp dẫn xuất. Nếu cha mẹ không có constructor parameterless và bạn không gọi bất kỳ, một lỗi thời gian biên dịch được báo cáo.