2011-12-09 66 views
8

Trong ví dụ sau:Gọi một phương pháp ghi đè từ một constructor

class Base {  
    int x=10; 

    Base() {  
     show(); 
    } 

    void show() { 
     System.out.print ("Base Show " +x + " "); 
    } 
} 

class Child extends Base { 
    int x=20; 

    Child() { 
     show(); 
    } 

    void show() {  
     System.out.print("Child Show " + x +" ") ; 
    } 

    public static void main(String s[ ]) { 
     Base obj = new Child(); 
    } 
} 
  • Tại sao là sản phẩm như hình dưới đây
Child Show 0 Child Show 20 
  • Tôi nghĩ nhà xây dựng có thể chỉ truy cập các thành viên cá thể khi nhà xây dựng siêu của nó s đã hoàn thành.

Tôi nghĩ điều đang xảy ra ở đây là nhà xây dựng siêu đang gọi phương thức show() của trẻ vì phương pháp này bị ghi đè trong Child. vì nó đã bị ghi đè nhưng tại sao giá trị của x 0 và tại sao nó có thể truy cập phương thức này trước khi hàm tạo siêu hoàn thành?

+0

là cơ chế xử lý ảo được kích hoạt trong quá trình thi của một đối tượng? Tôi nghi ngờ nó không phải là. – Mahesh

+0

Trong C++, điều này có thể gây ra sự cố. –

+3

Java hiệu quả là một tài nguyên Java tuyệt vời và nó đi sâu vào chi tiết này. Từ mục 17: "*** Các nhà xây dựng không được gọi các phương thức ghi đè **, trực tiếp hoặc gián tiếp (...) Nếu phương pháp ghi đè phụ thuộc vào bất kỳ khởi tạo nào được thực hiện bởi hàm tạo lớp con, phương thức sẽ không hoạt động như mong đợi ... * "Nếu bạn có cuốn sách trên tay tôi khuyên bạn nên đọc mục này. –

Trả lời

11

Tôi nghĩ điều đang xảy ra ở đây là nhà xây dựng siêu đang gọi phương thức show() của đứa trẻ vì phương pháp này đã được overriden trong Child.

Đó là đúng

nhưng tại sao là giá trị của x 0

bởi vì nó không được khởi tạo chưa (x của trẻ em)

và tại sao nó có thể để truy cập phương thức này trước khi hàm tạo siêu hoàn thành?

Đó chính xác là lý do tại sao trong một hàm tạo, bạn không bao giờ nên gọi một phương thức, có thể bị ghi đè (không công khai và được bảo vệ).

Chỉnh sửa:

Điều kỳ lạ ở đây là mọi thứ đều có chế độ hiển thị mặc định/gói riêng tư. Điều này có thể có một số hiệu ứng lạ. Xem: http://www.cooljeff.co.uk/2009/05/03/the-subtleties-of-overriding-package-private-methods/

Tôi khuyên bạn nên tránh các phương pháp ghi đè với khả năng hiển thị mặc định nếu có thể (bạn có thể ngăn chặn điều này bằng cách tuyên bố chúng cuối cùng).

+1

+1 Trình tự là chính -> Child() -> Base() -> Child.show() [x chưa được khởi tạo] -> Base.show() [trước bởi Base.x = 20] – stacker

+0

Không, sequence là main -> Base() -> Child.show() [x chưa được khởi tạo] -> Child() [Child.x = 20] -> Child.show() – Puce

+0

biến x trên lớp Child có được đưa ra một giá trị mặc định là 0 khi lớp Object đã được hoàn thành? Bởi vì như xa như tôi có thể nhớ ở đây là trình tự: new Child() -> Base() -> Object -> Triển khai thực hiện của trẻ() ... – anathema

6

Bạn có thể gọi các phương pháp ghi đè từ các nhà thầu, nhưng đó là xấu và bạn không nên. Bạn đã minh họa lý do tại sao điều này là xấu: lớp dẫn xuất không có cơ hội được khởi tạo, vì vậy các trường chưa được khởi tạo sẽ được sử dụng - trong ví dụ của bạn, mặc định cho int x là 0, đó là lý do tại sao nó in 0.

2

hàm tạo chuỗi có ý nghĩa để giải thích chính xác đó là gì. Nhiệm vụ đầu tiên của phương thức khởi tạo của lớp con là gọi phương thức khởi tạo của lớp bậc trên.Điều này đảm bảo rằng việc tạo đối tượng lớp con bắt đầu bằng việc khởi tạo các lớp ở trên nó trong chuỗi kế thừa.

http://java.about.com/b/2009/02/07/java-term-of-the-week-constructor-chaining.htm

http://javahours.blogspot.com/2008/12/constructor-chain.html

Các vấn đề liên quan