2012-12-31 40 views
5

Tôi đã tìm kiếm trực tuyến cho câu hỏi tương tự, nhưng không thể tìm thấy nó. Vì vậy, đăng ở đây.Thừa kế Java - từ khóa này

Trong chương trình sau đây tại sao giá trị của 'i' được in là 100?

AFAIK 'this' dùng để chỉ đối tượng hiện tại; trong trường hợp này là 'TestChild' và tên lớp cũng được in chính xác. Nhưng tại sao giá trị của biến mẫu không phải là 200?

public class TestParentChild { 
    public static void main(String[] args) { 
     new TestChild().printName(); 
    } 
} 

class TestChild extends TestParent{ 
    public int i = 200; 
} 

class TestParent{ 
    public int i = 100; 
    public void printName(){ 
     System.err.println(this.getClass().getName()); 
     System.err.println(this.i); //Shouldn't this print 200 
    } 
} 

Và hơn thế nữa, kết quả đầu ra sau đây như tôi mong đợi. Phương thức lớp con được gọi, khi tôi gọi "this.test()" từ lớp cha.

public class TestParentChild { 
    public static void main(String[] args) { 
     new TestChild().printName(); 
    } 
} 

class TestChild extends TestParent{ 
    public int i = 200; 
    public void test(){ 
     System.err.println("Child Class : "+i); 
    } 

} 

class TestParent{ 
    public int i = 100; 
    public void printName(){ 
     System.err.println(this.getClass().getName()); 
     System.err.println(this.i); //Shouldn't this print 200 
     this.test(); 
    } 
    public void test(){ 
     System.err.println("Parent Class : "+i); 
    } 
} 

Trả lời

7

Java không có lĩnh vực ảo, vì vậy i trường trong printName luôn đề cập đến TestParent.i và không bất kỳ con hậu duệ.

Polymorphism thông qua thừa kế trong Java chỉ xảy ra với các phương pháp, vì vậy nếu bạn muốn hoạt động bạn đang mô tả thì bạn muốn này:

class TestChild extends TestParent{ 

    private int i = 200; 

    @Override 
    public int getI() { return this.i; } 
} 

class TestParent{ 

    private int i = 100; 

    public int getI() { return this.i; } 

    public void printName(){ 
     System.err.println(this.getClass().getName()); 
     System.err.println(this.getI()); // this will print 200 
    } 
} 
+0

Cảm ơn đã trả lời nhanh chóng . Bạn có thể vui lòng eloberate, bạn có ý nghĩa gì bởi điều này? ** "Trong các trường Java không thể được đánh dấu là ảo" ** Như tôi đã đề cập, trong chương trình thứ hai của tôi, phương thức cá thể được gọi một cách chính xác. Nhưng biến mẫu là tham chiếu đến lớp Parent. – Jack

+0

Tôi đã cập nhật câu trả lời của mình. – Dai

+1

Trong Java, tất cả các phương thức (trừ khi được chỉ định) là "ảo", có nghĩa là chúng có một vtable được liên kết cho phép gửi thời gian chạy. Các trường, tuy nhiên, tồn tại như là một vị trí bộ nhớ tuyệt đối (ish) và không được bù đắp bởi bất kỳ vtable nào. Tôi đổ lỗi cho sự nhầm lẫn trên tài liệu thiết kế của Java mà không có từ khóa "ảo" và "ghi đè" rõ ràng trong khi C# làm. – Dai

2

Bởi vì lĩnh vực trong Java không được thừa kế. Sử dụng các khai báo của bạn, bạn đã khai báo hiệu quả hai trường khác nhau có tên là i và các phiên bản TestChild sẽ có cả hai. Khi TestParent được biên soạn, tham chiếu đến i theo các phương pháp của nó sẽ luôn tham chiếu đến TestParent.i.

+2

Các trường được kế thừa, không được ghi đè. – Dai

+0

Chắc chắn, đó là phrasing tốt hơn. – Dolda2000

2

Không có cách nào để ghi đè lên biến lớp.

Bạn không ghi đè lên các biến lớp trong Java, thay vào đó bạn ẩn chúng. Ghi đè là đối với các phương thức dụ và việc ẩn khác với việc ghi đè. Trong ví dụ bạn đã đưa ra, bằng cách khai báo biến lớp với tên 'i' trong lớp TestChild bạn ẩn biến lớp mà nó sẽ thừa hưởng từ siêu lớp của nó TestParent có cùng tên 'i'. Ẩn một biến theo cách này không ảnh hưởng đến giá trị của biến lớp 'i' trong lớp cha TestParent

Để có được hành vi mong muốn, bạn chỉ có thể ghi đè lên các phương pháp getI()

class TestChild extends TestParent{ 

    private int i = 200; 

    @Override 
    public int getI() { 
     return this.i; 
    } 
} 
+0

Cảm ơn rất nhiều câu trả lời của bạn. Tôi đã đọc về việc che giấu (bóng tối), nhưng quên nó đi. :(Cảm ơn bạn lần nữa. – Jack

+0

bạn được chào đón :) – Rahul