2012-03-28 19 views
6

Đây là đoạn mã, tôi định nghĩa hai lớp tên là Cha và Con, và tạo ra chúng trong các chức năng chính:Thứ tự của các Constructors trong Mã Java này là gì?

public class Test { 
    public static void main(String[] args) { 
     Father father = new Son(); 
    } 
} 

class Father { 
    private String name = "father"; 
    public Father() { 
     who(); 
     tell(name); 
    } 
    public void who() { 
     System.out.println("this is father"); 
    } 
    public void tell(String name) { 
     System.out.println("this is " + name); 
    } 
} 

class Son extends Father { 
    private String name = "son"; 
    public Son() { 
     who(); 
     tell(name); 
    } 
    public void who() { 
     System.out.println("this is son"); 
    } 
    public void tell(String name) { 
     System.out.println("this is " + name); 
    } 
} 

và tôi đã nhận kết quả như thế này:

this is son 
this is father 
this is son 
this is son 

Nhưng tôi không thể hiểu điều này đã xảy ra như thế nào? Bất cứ ai cũng có thể cho tôi biết lý do tại sao?

+5

Bài học không tìm hiểu: Không gọi các phương thức từ các nhà thầu có thể bị ghi đè. – Thilo

+2

bài học khác để học được là bạn nên luôn cố gắng tìm ra thông báo "gỡ lỗi" không thể hiểu sai: tôi sẽ thay đổi phương thức của bạn thành một cái gì đó như 'System.out.println (" Son.who() "); ',' System.out.println ("Son.tell (" + name + ")"); ',' System.out.println ("Cha.who()"); 'và' System.out. println ("Cha.tell (" + tên + ")"); ' –

Trả lời

9
  1. Hãy bắt đầu với các nhà xây dựng của Son.

    public Son() { 
        super(); // implied 
        who(); 
        tell(name); 
    } 
    
  2. Trình xây dựng của cha được gọi.

    public Father() { 
        who(); 
        tell(name); 
    } 
    
  3. who() được ghi đè bởi Son, phiên bản 's Son sẽ được gọi, in ấn "này là con trai".

  4. tell() cũng bị ghi đè nhưng giá trị được chuyển vào là Father.name, in "đây là cha".

  5. Cuối cùng, các cuộc gọi who()tell(name) bên trong số Son của hàm tạo sẽ được in lần lượt là "con này" và "con này".

3

Khi bạn tạo ví dụ Son, hàm tạo của lớp cha được gọi (ví dụ: Father()); ở đây phương thức who() được gọi, nhưng đó là phiên bản ghi đè bạn đã khai báo trong Son, vì vậy đây là dòng đầu tiên của bạn (trong đó Chuỗi được mã hóa cứng bên trong phương thức).

Dòng thứ hai xuất phát từ bên trong tell(name)Father(), nơi tell() sẽ bị thay thế nhưng name == "father" như các cuộc gọi đến từ bên trong constructor Father 's, và name là một lĩnh vực private của lớp Father.

Điều khiển quay trở lại Son() hàm tạo và hai dòng cuối cùng trở nên đơn giản từ hàm tạo lớp Son.

2

Father() được gọi trước Son(). Trình tạo mặc định của lớp bậc trên được gọi ngầm, chúng tôi không cần câu lệnh super() tại đây.

who() bên trong hàm tạo Father() gọi phương thức ghi đè.

5

Dưới đây là những gì được gọi là:

new Son() 
=> 
    Son._init 
    => first every constructor calls super() 
     Father._init 
     Object._init 
     who() => is overridden, so prints "son" 
     tell(name) => name is private, so cannot be overridden => "father" 
    who() => "son" 
    tell(name) => "son" 

bài học để học:

  • lĩnh vực tư nhân và phương pháp tư nhân. Không thể ghi đè.
  • Không gọi các phương thức từ các nhà thầu có thể bị ghi đè. Điều này có thể gọi các phương thức trên trạng thái lớp nửa khởi tạo (không xảy ra trong trường hợp của bạn).
0

Mã trên đặc biệt là Kiểu xấu (TM). ;-)

Điều gì xảy ra là: Không có trường hợp của Cha, chỉ là một trường hợp Sơn. (Tuy nhiên, đó là sự phân công tương thích với Chúa Cha.)

Nhà xây dựng của Son gọi người xây dựng Cha. Sau này gọi các phương thức ghi đè (!), Do đó Cha.who và Cha.tell không bao giờ được gọi! Các phương thức ghi đè được gọi trước (!) Constructor Son được hoàn thành.

khuyến nghị của tôi:

  1. Nếu bạn gọi một phương pháp trong một constructor, làm cho nó thức. Hoặc làm cho toàn bộ lớp học cuối cùng. Hoặc làm cho phương thức được gọi là riêng tư ít nhất.
  2. Không bao giờ ghi đè lên phương thức được gọi trong hàm tạo.
  3. Nếu bạn phải vi phạm các đề xuất trên, hãy viết ý kiến ​​rộng rãi về lý do bạn đã làm như vậy và những gì bạn mong đợi sẽ xảy ra. Viết một bài kiểm tra đơn vị để đảm bảo các giả định của bạn là hợp lệ.
Các vấn đề liên quan